Assignment 1: The Basics
In the first assignment, you will employ some basic techniques to control the look of your document and how R code chunks are rendered. We will cover YAML metadata modifications, setting global chunk options, and writing Markdown content. You will also learn about testing R code first before rendering the final document.
1.1 Make a Document
If you have not already done so, your first task is to create an R Markdown document. Open R Studio and go to File > New File > R Markdown. A window should pop up where you can fill in the details. It is not important what you put here since you can change it at any time. What is important is that Document and HTML are both selected. We will cover other document types in the future. Hit Ok and follow the steps in this graphic. Remember, you do not need to add a file extension when you save the document.
Once you have a document built and saved, there should be a .html file in your working directory. Double-click that file—it should open in your default browser. Each time you re-knit the .Rmd file, you can just refresh the browser page or double-click the file again.
1.2 Add Markdown Text
Your first task is to add some content and format the content with Markdown. This doesn’t need to be anything fancy to start. You can either add text as you go or paste a large amount of text in at once. Dealers choice. You can use the Markdown section of Lesson 0 or the Markdown section from the Resources page for reference.
- Add headers to give the document structure. Use different header levels.
- Add hyperlinks. We will learn about internal links later. For now, just link to outside websites.
- Add emphasis formatting like bold, italics, and block text.
- Mix and match formatting, like make a hyperlink bold or add italics to block text.
- Make a list of items.
1.3 Modify & Test R Code Chunks
Now it is time to get some practice modifying code chunk options so you can gain more control over the behavior of code and result display. If you have your own R code you are more than welcome to use it here. I will use the default code chunks that were added to the .Rmd file. Please see the section on Chunk structure & options from Lesson 2 for more details.
Here are the two default code chunks. As you can see, both have names and the second chunk has a single option.
```{r cars}
summary(cars)
```
```{r pressure, echo=FALSE}
plot(pressure)
```
There are many code chunk options you can control. Which options you use and how you set them will be determined by your needs. Test the behavior of the following options by setting each equal to either TRUE or FALSE. Render the document and see if you can figure out what changed. Each of these has a default value so you may not see a change until you set the alternative value.
echo
collapse
eval
prompt
highlight
include
Next, it is a really good habit to check code chunks as you add them. This will ensure that each chunk works, making it easier to track down problems. If you refer to the first image on this page, you can you have options for Chunk Output—Inline and Console. This controls where the output is displayed. Let’s take a quick look at a code chunk in RStudio and see how you test chunks before rendering.

Take a look at the tool bar on the far right. Option 1 is a drop down menu that gives you an alternative way to set code chunk options. Option 2 will Run all Code Chunks Above meaning that RStudio will run all code chunks above the current chunk but not the current chunk itself. And Option 3 will Run the Current Chunk. Incidentally, if you do not see these options it means something is wrong with the chunk.
Go ahead and run the chunk.
Assignment 2: Tables
In this assignment, you will explore different methods of incorporating tables in your document. The choice of method depends on a) the type of data, b) the amount of data, and c) the desired output. I will cover a few tools for creating tables but please note there are many options out there, so look around and let us know if you find a tool you like.
For each example, I will use the mtcars data set from the datasets package. The mtcars data set has 32 rows and 11 columns. Feel free to load your own data table or use the mtcars data set.
2.1 Markdown
The simplest method of building a table is with Markdown syntax. This is a nice option because you can hard code the table right into the document—no need to install and load libraries or write code chunks—and it is easy to implement. The downside is there is minimal functionality available in a Markdown table.
Markdown does not work well for large tables. So I will first grab a subset of mtcars, specifically the first 4 rows and 3 columns. In my code chunk I add the chunk option comment="". This prevents knit from appending a string (default is ##) to the start of each line of results in the final document.
mpg cyl disp
Mazda RX4 21.0 6 160
Mazda RX4 Wag 21.0 6 160
Datsun 710 22.8 4 108
Hornet 4 Drive 21.4 6 258
Incidentally, the results box above is technically the simplest table you can make, either by calling the data frame mtcars_sub directly or running print.data.frame(mtcars_sub).
Anyway, run this code chunk, copy the results, and make a Markdown table. You can either run the chunk in RStudio without rendering the document (described above) or render the document and copy the results from HTML page. I added a header to the first column. And here is the Markdown table.
Since this is a Markdown table, you can add additional Markdown syntax for formatting. See if you can figure out what syntax I added to my table and add some to your table. Also check out the Tables section of PanDoc User’s Guide for other Markdown table options, including how to add a caption. In addition to pipe_tables, you can create multiline_tables grid_tables, and simple_tables.
Something to notice is that the Markdown table spans the entire width of the page—even though it does not need all of that space. As far as I know, there is no way to control this behavior without adding additional HTML formatting.
Recommendation Use Markdown for small, simple tables where styling is not a concern.
2.2 R Markdown Paged Tables
With larger tables, it may not be practical to display the full table inline. So we need a way to shrink a large table so it looks good while still allowing access to the full table.
The next type of table I want you to try are Paged Tables. R Markdown comes with its own built in table function called paged_table. The paged_table function allows pagination of rows and columns making it possible to render a large table in a small space.
It is easy to code paged_table but that ease comes with a small price—limited functionality. Here are the options you do have with paged_table function.
A Markdown table listing the Options for the paged_table function.
rows.print |
Maximum rows to print per page. |
max.print |
Maximum rows in the table (defaults to 1000). |
cols.print |
Maximum columns in the table (defaults to 10). |
rownames.print |
Print row names as part of the table. |
A quick side note. You actually need to load the rmarkdown package for paged_table to work. Anyway, this is a good time to return to the first code chunk in your .Rmd file—the chunk called setup that R Markdown added by default.
I like to use this chunk to load all of the packages I need for my document. Using a single chunk for all of my packages helps me keep my document organized. Notice the setup chunk has the option include=FALSE. This prevents the content of the chunk from appearing in the final document, which for me is more stylistically appealing. I can add a sessionInfo() chunk at the end of my document to report all of the packages so this information is available to the reader. We will cover sessionInfo() when we get into more depth on the subject of reproducible. If you do not want to load the library you can run the command like this: rmarkdown::paged_table().
OK, back to the table. Now I can create a table of mtcars with the paged_table function and use an option to limit the number of printed rows to 5 for each page. I used echo=FALSE in my code chunk to hide the code :). By now you should know where to look for a solution.
Notice that for each column, the column class is printed below the name (text enclosed in < >). This is irritating and related to printing a table from a built-in data frame. I have no idea how to fix this (within the confines of R Markdown) but I will work on a solution.
Recommendation Use paged_table for large tables where extensive styling is not a concern.
2.3 Kable Tables
Knitr comes with its own tool for rendering simple tables called kable. The documentation for kable can be found here or by running ?knitr::kable() in the Console. By itself, kable comes with almost no options. We can extend its functionality with the kableExtra package and piping syntax from magrittr. The features of kableExtra are extensive and I will only touch on a few here. The documentation for kableExtra can be found here or by running ?kableExtra in the Console after the package has been installed and loaded.
I highly recommend you learn how to use these packages for making tables.
Again, you will need to load kableExtra and either load the knitr package or run the command like this: knitr::kable().
First, let’s look at the default kable table output. We will use the head of the mtcars data set.
Wow, this table looks terrible.
|
|
mpg
|
cyl
|
disp
|
hp
|
drat
|
wt
|
qsec
|
vs
|
am
|
gear
|
carb
|
|
Mazda RX4
|
21.0
|
6
|
160
|
110
|
3.90
|
2.620
|
16.46
|
0
|
1
|
4
|
4
|
|
Mazda RX4 Wag
|
21.0
|
6
|
160
|
110
|
3.90
|
2.875
|
17.02
|
0
|
1
|
4
|
4
|
|
Datsun 710
|
22.8
|
4
|
108
|
93
|
3.85
|
2.320
|
18.61
|
1
|
1
|
4
|
1
|
|
Hornet 4 Drive
|
21.4
|
6
|
258
|
110
|
3.08
|
3.215
|
19.44
|
1
|
0
|
3
|
1
|
|
Hornet Sportabout
|
18.7
|
8
|
360
|
175
|
3.15
|
3.440
|
17.02
|
0
|
0
|
3
|
2
|
|
Valiant
|
18.1
|
6
|
225
|
105
|
2.76
|
3.460
|
20.22
|
1
|
0
|
3
|
1
|
If we tried to render the entire table by omitting head, we would just get a long, crappy table in our document. Not cool. Lets see if we can jazz this up a bit with kableExtra.
This table looks better
|
|
mpg
|
cyl
|
disp
|
hp
|
drat
|
wt
|
qsec
|
vs
|
am
|
gear
|
carb
|
|
Mazda RX4
|
21.0
|
6
|
160
|
110
|
3.90
|
2.620
|
16.46
|
0
|
1
|
4
|
4
|
|
Mazda RX4 Wag
|
21.0
|
6
|
160
|
110
|
3.90
|
2.875
|
17.02
|
0
|
1
|
4
|
4
|
|
Datsun 710
|
22.8
|
4
|
108
|
93
|
3.85
|
2.320
|
18.61
|
1
|
1
|
4
|
1
|
|
Hornet 4 Drive
|
21.4
|
6
|
258
|
110
|
3.08
|
3.215
|
19.44
|
1
|
0
|
3
|
1
|
|
Hornet Sportabout
|
18.7
|
8
|
360
|
175
|
3.15
|
3.440
|
17.02
|
0
|
0
|
3
|
2
|
|
Valiant
|
18.1
|
6
|
225
|
105
|
2.76
|
3.460
|
20.22
|
1
|
0
|
3
|
1
|
Here I used the pipe operator (%>%) to pass the results of kable to the function kable_styling—a part of the kableExtra package. By running kable_styling as is, I am using defaults for all of the options.
The pipe operator is a powerful tool worth learning.
Back to the table. It certainly looks better than the default kable version but we are missing the ability to page the table. I would like you to run these two commands and look at the output.
This command will include the whole table.
kable(mtcars) %>%
kable_styling()
And this command will transpose the table (swap rows and columns) using the transpose (t) function. Remember, mtcars has 32 rows and 11 columns but when you transpose the table, it has 11 rows and 32 columns. So it is really wide in the transposed state.
kable(head(t(mtcars))) %>%
kable_styling()
I hope you agree that neither of these tables are acceptable, especially the second one. Unfortunately, the kableExtra package does not come with an option to add pagination. You can however put the table in a fixed-height, fixed-width (or both) box, and make it scrollable. We can do this by using a pipe operator and the scroll_box function. While we are at it, lets also add tweak some options in kable_styling to make a more handsome table.
Scrollable kable table.
|
|
Mazda RX4
|
Mazda RX4 Wag
|
Datsun 710
|
Hornet 4 Drive
|
Hornet Sportabout
|
Valiant
|
Duster 360
|
Merc 240D
|
Merc 230
|
Merc 280
|
Merc 280C
|
Merc 450SE
|
Merc 450SL
|
Merc 450SLC
|
Cadillac Fleetwood
|
Lincoln Continental
|
Chrysler Imperial
|
Fiat 128
|
Honda Civic
|
Toyota Corolla
|
Toyota Corona
|
Dodge Challenger
|
AMC Javelin
|
Camaro Z28
|
Pontiac Firebird
|
Fiat X1-9
|
Porsche 914-2
|
Lotus Europa
|
Ford Pantera L
|
Ferrari Dino
|
Maserati Bora
|
Volvo 142E
|
|
mpg
|
21.00
|
21.000
|
22.80
|
21.400
|
18.70
|
18.10
|
14.30
|
24.40
|
22.80
|
19.20
|
17.80
|
16.40
|
17.30
|
15.20
|
10.40
|
10.400
|
14.700
|
32.40
|
30.400
|
33.900
|
21.500
|
15.50
|
15.200
|
13.30
|
19.200
|
27.300
|
26.00
|
30.400
|
15.80
|
19.70
|
15.00
|
21.40
|
|
cyl
|
6.00
|
6.000
|
4.00
|
6.000
|
8.00
|
6.00
|
8.00
|
4.00
|
4.00
|
6.00
|
6.00
|
8.00
|
8.00
|
8.00
|
8.00
|
8.000
|
8.000
|
4.00
|
4.000
|
4.000
|
4.000
|
8.00
|
8.000
|
8.00
|
8.000
|
4.000
|
4.00
|
4.000
|
8.00
|
6.00
|
8.00
|
4.00
|
|
disp
|
160.00
|
160.000
|
108.00
|
258.000
|
360.00
|
225.00
|
360.00
|
146.70
|
140.80
|
167.60
|
167.60
|
275.80
|
275.80
|
275.80
|
472.00
|
460.000
|
440.000
|
78.70
|
75.700
|
71.100
|
120.100
|
318.00
|
304.000
|
350.00
|
400.000
|
79.000
|
120.30
|
95.100
|
351.00
|
145.00
|
301.00
|
121.00
|
|
hp
|
110.00
|
110.000
|
93.00
|
110.000
|
175.00
|
105.00
|
245.00
|
62.00
|
95.00
|
123.00
|
123.00
|
180.00
|
180.00
|
180.00
|
205.00
|
215.000
|
230.000
|
66.00
|
52.000
|
65.000
|
97.000
|
150.00
|
150.000
|
245.00
|
175.000
|
66.000
|
91.00
|
113.000
|
264.00
|
175.00
|
335.00
|
109.00
|
|
drat
|
3.90
|
3.900
|
3.85
|
3.080
|
3.15
|
2.76
|
3.21
|
3.69
|
3.92
|
3.92
|
3.92
|
3.07
|
3.07
|
3.07
|
2.93
|
3.000
|
3.230
|
4.08
|
4.930
|
4.220
|
3.700
|
2.76
|
3.150
|
3.73
|
3.080
|
4.080
|
4.43
|
3.770
|
4.22
|
3.62
|
3.54
|
4.11
|
|
wt
|
2.62
|
2.875
|
2.32
|
3.215
|
3.44
|
3.46
|
3.57
|
3.19
|
3.15
|
3.44
|
3.44
|
4.07
|
3.73
|
3.78
|
5.25
|
5.424
|
5.345
|
2.20
|
1.615
|
1.835
|
2.465
|
3.52
|
3.435
|
3.84
|
3.845
|
1.935
|
2.14
|
1.513
|
3.17
|
2.77
|
3.57
|
2.78
|
|
qsec
|
16.46
|
17.020
|
18.61
|
19.440
|
17.02
|
20.22
|
15.84
|
20.00
|
22.90
|
18.30
|
18.90
|
17.40
|
17.60
|
18.00
|
17.98
|
17.820
|
17.420
|
19.47
|
18.520
|
19.900
|
20.010
|
16.87
|
17.300
|
15.41
|
17.050
|
18.900
|
16.70
|
16.900
|
14.50
|
15.50
|
14.60
|
18.60
|
|
vs
|
0.00
|
0.000
|
1.00
|
1.000
|
0.00
|
1.00
|
0.00
|
1.00
|
1.00
|
1.00
|
1.00
|
0.00
|
0.00
|
0.00
|
0.00
|
0.000
|
0.000
|
1.00
|
1.000
|
1.000
|
1.000
|
0.00
|
0.000
|
0.00
|
0.000
|
1.000
|
0.00
|
1.000
|
0.00
|
0.00
|
0.00
|
1.00
|
|
am
|
1.00
|
1.000
|
1.00
|
0.000
|
0.00
|
0.00
|
0.00
|
0.00
|
0.00
|
0.00
|
0.00
|
0.00
|
0.00
|
0.00
|
0.00
|
0.000
|
0.000
|
1.00
|
1.000
|
1.000
|
0.000
|
0.00
|
0.000
|
0.00
|
0.000
|
1.000
|
1.00
|
1.000
|
1.00
|
1.00
|
1.00
|
1.00
|
|
gear
|
4.00
|
4.000
|
4.00
|
3.000
|
3.00
|
3.00
|
3.00
|
4.00
|
4.00
|
4.00
|
4.00
|
3.00
|
3.00
|
3.00
|
3.00
|
3.000
|
3.000
|
4.00
|
4.000
|
4.000
|
3.000
|
3.00
|
3.000
|
3.00
|
3.000
|
4.000
|
5.00
|
5.000
|
5.00
|
5.00
|
5.00
|
4.00
|
|
carb
|
4.00
|
4.000
|
1.00
|
1.000
|
2.00
|
1.00
|
4.00
|
2.00
|
2.00
|
4.00
|
4.00
|
3.00
|
3.00
|
3.00
|
4.00
|
4.000
|
4.000
|
1.00
|
2.000
|
1.000
|
1.000
|
2.00
|
2.000
|
4.00
|
2.000
|
1.000
|
2.00
|
2.000
|
4.00
|
6.00
|
8.00
|
2.00
|
For the scroll_box function I set the width = "100%" rather than specifying a dimension. This ensures the box will always be the width of the page no matter how small the window is.
Even though you cannot make a paged table with kable, there are many styling options available in the kableExtra package that makes this method extremely useful and worth learning. Plus, the code is relatively simple to write.
I want to show you one more feature that is not available the other table methods we cover in this Assignment—floating. Let’s first subset the mtcars data set so we can make a small table. Next we use the full_width and position options to control the size and position of the table.
Here is our code chunk.
|
|
mpg
|
cyl
|
disp
|
hp
|
drat
|
wt
|
|
Mazda RX4
|
21.0
|
6
|
160
|
110
|
3.90
|
2.620
|
|
Mazda RX4 Wag
|
21.0
|
6
|
160
|
110
|
3.90
|
2.875
|
|
Datsun 710
|
22.8
|
4
|
108
|
93
|
3.85
|
2.320
|
|
Hornet 4 Drive
|
21.4
|
6
|
258
|
110
|
3.08
|
3.215
|
|
Hornet Sportabout
|
18.7
|
8
|
360
|
175
|
3.15
|
3.440
|
|
Valiant
|
18.1
|
6
|
225
|
105
|
2.76
|
3.460
|
|
Duster 360
|
14.3
|
8
|
360
|
245
|
3.21
|
3.570
|
Let’s say we have a bunch of text that we want to put side-by-side with this small table. Our subsetted mtcars data set now has 7 rows and 6 columns. We can make our table smaller by setting full_width = FALSE in kable_styling and float the table by setting position = "float_right"
Please study the extensive options available in kable and kableExtra and create tables that implement some of the options.
Recommendation Use kable + kableExtra for small tables where extensive styling is desired.
2.4 DT Tables
The last option I want to cover for building tables is implemented using the datatable function from the DT package, an interface to the JavaScript library DataTables. To demonstrate the functionality, I will use a larger data set called USJudgeRatings from the datasets package. USJudgeRatings has 43 rows and 12 columns. This table is too big—horizontally and vertically—to fit on a standard page.
The syntax for the DT::datatable is more complicated than the other methods but that comes with more extensive functionality.
Working with DT::datatable is an advanced level skill. I highly recommend you learn how to use the package, but it will take practice.
Please make sure you are comfortable with the other methods first before trying to use DT::datatable. I promise, if you do not know what you are doing, this package will cause a lot of frustration. That said, I use it all the time because it is awesome.
Moving on. If we run DT on the USJudgeRatings data set without any options the table will spill off the side of the page. Again, not cool. Try to run this command and see what happens.
datatable(USJudgeRatings)
DT::datatable does not page tables horizontally like the paged_table command does (described above). We can set the width of the table and add an option that allows horizontal scrolling. For this we use the options argument. The syntax is to add width = "100%" followed by options = list(), where we put a comma separated list of options. For now, we just include scrollX in our list of options.
Play around with the table a little. As you can see
- the table now fits in the window,
- horizontal scrolling in enabled,
- the page is vertically paged,
- there is a Show entries drop down, and
- there is a Search box.
The Show entries and Search box are added by default. We can decide whether to show these options or not. I will save that for later. For now, I want to leave you with a more stylized DT data table to give you a sense of the possibilities. Don’t worry so much about the code—pay attention to the functionality.
datatable(USJudgeRatings, width = "100%",
extensions = 'Buttons', options = list(
scrollX = TRUE,
dom = 'lfrtipB',
buttons = c('copy', 'csv', 'excel', 'pdf', 'print'),
pageLength = 5,
lengthMenu = c(5, 10, 20, 45)
)
)
I added buttons to download the table to different formats, changed the page length to 5, and changed the values in the Show entries drop down. Play around with the table. There is a lot more to do with this package and we will come back to it often.
Recommendation Use DT::datatable for large tables where extensive styling is desired.
That’s all for this assignment.
Assignment 3: Code
If you are interested in making your science more transparent and reproducible, you need to provide at least two things—the raw data you generated and the code you used to analyze it. Hopefully it is obvious by now that you need to provide access to both components; neither is particularly useful without the other. We will cover data availability in a future lesson. For this assignment, you will practice several different methods for making your code accessible. The method or methods you choose for your own work will depend on the type of analyses and the type of code.
Your assignment is to implement these methods in your document and play around with the different options.
Purl
Knitr comes with a built-in function called purl, which allows you to extract all the R code from an R Markdown document and convert it to an R script. In order to run purl, you must either load the knitr library first (i.e., library(knitr)) and then run purl or call the function directly by running knitr::purl(). We will start by discussing some simple options for running purl and then talk about how you run the command. The basic structure of the command is:
knitr::purl(input="filename.Rmd", documentation = L)
By default, purl uses the base name of the input file as the base name of the output file. If you want to control this behavior, add the option output="filename.R" where filename is whatever you choose.
The option documentation is an integer that specifies the level (L) of documentation to add to the script. You have three choices
- 0 means output pure code to the script, discard all Markdown text and code chunk details.
- 1 (the default) means discard all Markdown text but add the chunk headers to the script as commented lines.
- 2 means to add all Markdown text and code chunks to the script as commented lines.
As far as I know, you cannot run purl from inside an actual code chunk. I have no idea why nor was I able to find an answer. If have an answer or know a solution, please let us know. There easiest way to generate an R script from an R Markdown document with purl to is to run the command in the Console like so:
knitr::purl(input="filename.Rmd", documentation = 1)
Run the purl command using the three options described above for documentation option and look at the output files.
Inline R expressions are ignored by default. For example, if you had an inline R expression like this `r sqrt(2)` the expression would not be included in the R script generated by purl. If you want to include inline expressions in the R script, you need to set the global R option knitr.purl.inline = TRUE before calling knitr::purl().
Remember way back when you generated your initial R Markdown document a default code chunk was added just below the YAML header?
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
If you add knitr.purl.inline = TRUE to that code chunk, all inline expressions will be added to the R script.
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE, knitr.purl.inline = TRUE)
```
The last thing I want to mention is that you can prevent certain code chunks from appearing in the R Script by adding the option purl = FALSE to the chunk. For example, if you add this option to the setup chunk we just discussed that chunk will not appear in the final document.
```{r setup, include=FALSE, purl = FALSE}
knitr::opts_chunk$set(echo = TRUE, knitr.purl.inline = TRUE)
```
Test the behavior of the different options for purl on your document. You can also use this funtion on any R Markdown document to quickly retrieve the code. For example, if you download the Rmd file for this page from GitHub you can run purl to quickly extract the R code.
Recommendation Use purl to generate a simple R script version of your R Markdown document after the document is finished and saved. You can then link to the file somewhere in your document.
Download Rmd
I hope by now you have seen that any document I present in this course has a link to a GitHub repo where you can download or copy the .Rmd file. That’s great and all, but wouldn’t it be nice if you could do it right from the HTML page? Well, you can by adding one simple line of code as a property of html_document in your YAML header —code_download: true.
output:
html_document:
theme: journal
toc: true
toc_float: true
toc_depth: 3
highlight: tango
code_download: true
You could of course set the property to false except this is the default value and nothing will change. Look back at the top of this page and you should now see a Code button in the upper right corner. Click on the drop down and select Download Rmd and this entire page should be saved to your Downloads directory.
Go ahead and add this option to your YAML header.
Code Folding
I have mentioned a time or two that the benefits of using R Markdown is the ability to execute and display code in your final document. If you go back to the default setup chunk at the top of your .Rmd you should see this:
knitr::opts_chunk$set(echo = TRUE)
I discussed this chunk previously in #5 of the Chunk structure & options section in Lesson 2. Briefly, this is a global command that ensures all R code chunks are visible in the final document, unless you escape this behavior by using echo = FALSE in a particular chunk. Of course, you could also set the global option to FALSE as is knitr::opts_chunk$set(echo = FALSE) and then none of the R code would be visible at all. This is a perfectly fine option in some situations but not in others.
Let’s face it—code takes up a lot of space in a document and large code chunks are not particularly pleasing to look at. You may encounter situations where you both want the code available on a page but you also want to hide the code. For this we use a technique called code folding. Near the bottom of Lesson 0, I used some simple HTML to make a section that folds the R code for the Clifford Attractor. There is a little Show/hide button that allows you to look at the code if you want to; otherwise it is hidden by default. But this approach is a little clunky because you must a) know some HTML and b) include this for every chunk.
R Markdown has a similar functionality for showing and hiding code but it only takes a single line of code added to the YAML header. Again, return to your YAML header and add the argument code_folding: as a nested property of html_document:. Your two options for code_folding: are show and hide.
output:
html_document:
theme: journal
toc: true
toc_float: true
toc_depth: 3
highlight: tango
code_download: true
code_folding: hide
Once you add this to the YAML header, the drop down Code button in the upper right corner of the page should now include Show All Code and Hide All Code. This allows the user to specify how they want to view the code in the document. Either property you set for code_folding will be the default state for the entire document.
You should also notice that a new Code button appears next to every code chunk in your document. Again, if you want to exclude the code from individual chunks, just set echo = FALSE for that chunk and the code will not be included at all.
Add code_folding: argument to your YAML header and set a property value.
As far as I know there is no way of folding the results of a code chunk or folding indivudual chunks unless you use HTML.
That’s all for this assignment.
LS0tCnRpdGxlOiAiW0xlc3NvbiAyOiBZb3VyIFByYWN0aWNhbCBQYWdlXShodHRwczovL2dpdGh1Yi5jb20vc3RyaS1jb24vZGMtc2luZ2xlL2Jsb2IvbWFzdGVyL2luZGV4LlJtZCkiCmF1dGhvcjogImJ5IEphcnJvZCIKZGF0ZTogImByIGZvcm1hdChTeXMudGltZSgpLCAnJWQgJUIsICVZJylgIgpzbWFydDogdHJ1ZQpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIHRoZW1lOiBqb3VybmFsCiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgdG9jX2RlcHRoOiAzCiAgICBoaWdobGlnaHQ6IHRhbmdvCiAgICBrZWVwX21kOiB0cnVlCiAgICBzZWxmX2NvbnRhaW5lZDogdHJ1ZQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgY29kZV9mb2xkaW5nOiBoaWRlCiNvdXRwdXQ6CiMgIGVwdVJhdGU6OmVwdXJhdGU6CiMgICAgdG9jOiBUUlVFCiMgICAgbnVtYmVyX3NlY3Rpb25zOiBGQUxTRQojICAgIGNvZGVfZm9sZGluZzogInNob3ciCmVkaXRvcl9vcHRpb25zOgogIGNodW5rX291dHB1dF90eXBlOiBpbmxpbmUKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCBrbml0ci5wdXJsLmlubGluZSA9IFRSVUUpCnNldC5zZWVkKDkxMSkKYGBgCgpgYGB7ciBsb2FkX2xpYnMsIGluY2x1ZGU9RkFMU0V9CmxpYnJhcnkoa25pdHIpCmxpYnJhcnkoZXB1UmF0ZSkKbGlicmFyeShrYWJsZUV4dHJhKQpsaWJyYXJ5KHJtYXJrZG93bikKbGlicmFyeShEVCkKYGBgCgojIyBPdmVydmlldwoKV2VsY29tZSB0byB0aGUgaGFuZHMtb24sIHByYWN0aWNhbCBsZWFybmluZyBwb3J0aW9uIG9mIFtMZXNzb24gMl0oaHR0cHM6Ly9zdHJpLWNvbi5naXRodWIuaW8vZGF0YS1jdXJhdGlvbi8yMDIwLzA0LzA5L2xlc3Nvbi0yLykgd2hlcmUgeW91IHdpbGwgY3JlYXRlIGEgc2luZ2xlIHBhZ2UgUiBNYXJrZG93biBkb2N1bWVudC4gSSBtYWRlIHRoaXMgcGFnZSB0byBoZWxwIGd1aWRlIHlvdSBpbiB0aGUgcHJvY2Vzcy4gVGhlIG1hdGVyaWFsIGJlbG93IGNvbnRhaW5zIGEgc2VyaWVzIG9mIGFzc2lnbm1lbnRzIGFuZCBjaGFsbGVuZ2VzIGRlc2lnbmVkIHRvIGdldCB5b3UgY29tZm9ydGFibGUgdXRpbGl6aW5nIFtZQU1MIG1ldGFkYXRhXShodHRwczovL3N0cmktY29uLmdpdGh1Yi5pby9kYXRhLWN1cmF0aW9uLzIwMjAvMDQvMDkvbGVzc29uLTIvI3RoZS15YW1sLWhlYWRlci0xKSwgW01hcmtkb3duIHN5bnRheF0oaHR0cHM6Ly9zdHJpLWNvbi5naXRodWIuaW8vZGF0YS1jdXJhdGlvbi8yMDIwLzA0LzA5L2xlc3Nvbi0yLyNtYXJrZG93bi1mb3JtYXR0ZWQtdGV4dC0xKSwgYW5kIFtSIGNvZGUgY2h1bmtzXShodHRwczovL3N0cmktY29uLmdpdGh1Yi5pby9kYXRhLWN1cmF0aW9uLzIwMjAvMDQvMDkvbGVzc29uLTIvI3ItY29kZS1jaHVua3MtMSkuCgpUaGUgcGFnZSBpdHNlbGYgaXMgd3JpdHRlbiBhbG1vc3QgZW50aXJlbHkgaW4gUiBNYXJrZG93biwgbWVhbmluZyB0aGVyZSBpcyBubyBleHRlbnNpdmUgdXNlIG9mIGFueXRoaW5nIGZhbmN5IGxpa2UgY29tcGxpY2F0ZWQgIENTUyBvciBIVE1MLiBJIHdpbGwgaW50cm9kdWNlIHNvbWUgc2ltcGxlIEhUTUwgY29kZSB5b3UgY2FuIHVzZSB0byBqYXp6IHVwIHlvdXIgZG9jdW1lbnQgYSBsaXR0bGUuIFlvdSBzaG91bGQgYmUgYWJsZSB0byBzb2x2ZSBhbnkgcHJvYmxlbSBJIHByZXNlbnQgYnkgZGlnZ2luZyBhcm91bmQgaW4gdGhlIHJhdyBjb2RlIG9uIEdpdEh1YiwgY29uc3VsdGluZyB0aGUgW1Jlc291cmNlcyBwYWdlXShodHRwczovL3N0cmktY29uLmdpdGh1Yi5pby9kYXRhLWN1cmF0aW9uL3BhZ2UvcmVzb3VyY2VzLyksIHVzaW5nIG9uZSBvZiB0aGUgdGFyZ2V0ZWQgc2VhcmNoIHN0cmF0ZWdpZXMgZGVzY3JpYmVkIGluIHRoZSBbUHJvYmxlbSBTb2x2aW5nIHBvc3RdKGh0dHBzOi8vc3RyaS1jb24uZ2l0aHViLmlvL2RhdGEtY3VyYXRpb24vMjAyMC8wNC8wMy9oZWxwLyksIGFuZC9vciBwb3N0aW5nIGEgcXVlc3Rpb24gdG8gdGhlIFNsYWNrIGNoYW5uZWwuCgojIyBTb21lIEtleXMgdG8gU3VjY2VzcwoKPiAqKktuaXQgb2Z0ZW4qKi4gV2hlbmV2ZXIgeW91IG1ha2UgYSBjaGFuZ2UgdG8gdGhlIFlBTUwgaGVhZGVyLCBhZGQgYSBuZXcgY29kZSBjaHVuaywgZXRjLiwgcmUta25pdCAob3IgcmVuZGVyKSB5b3VyIGRvY3VtZW50LiBUaGlzIGlzIHZlcnkgaW1wb3J0YW50LiBSZWd1bGFyIGtuaXR0aW5nIGFsbG93cyB5b3UgdG8gKiphKiopIHNlZSB0aGUgZWZmZWN0cyBvZiBhIGNoYW5nZSBhbmQgKipiKiopIHRyYWNrIGRvd24gKHRyb3VibGVzaG9vdCkgaXNzdWVzIG1vcmUgZWFzaWx5Lgo+Cj4gU2ltcGx5IGhpdCB0aGUga25pdCBidXR0b24gb3IgdXNlIHRoZSBzaG9ydGN1dCBrZXlzLS0tb24gTWFjT1MgYENtZGArYFNoaWZ0YCtgS2AgYW5kIFdpbmRvd3MgYEN0cmxgK2BTaGlmdGArYEtgLiBMZWFybiB0byBsb3ZlIHRoZXNlIHNob3J0Y3V0IGtleXMuIFRoZXkgd2lsbCBzYXZlIHlvdSB0aW1lLgoKWW91IGNhbiBjaG9vc2UgaG93IHlvdXIgZG9jdW1lbnQgaXMgcHJldmlld2VkIHVzaW5nIHRoZSBkcm9wIGRvd24gbWVudSBpbiB0aGUgZG9jdW1lbnQgc2V0dGluZ3MuIGBQcmV2aWV3IGluIFdpbmRvd2Agb3BlbnMgdGhlIGRvY3VtZW50IGluIGEgc2VwYXJhdGUgUlN0dWRpbyB3aW5kb3cgYW5kIGBQcmV2aWV3IGluIFZpZXdlciBQYW5lYCBsZXRzIHlvdSBzZWUgdGhlIGRvY3VtZW50IGluIHRoZSBtYWluIFJTdHVkaW8gSURFLiBUaGVzZSBhcmUgZ29vZCBmb3IgKnF1aWNrKiBsb29rcy4gWW91IHNob3VsZCAqKmFsd2F5cyoqIGRvdWJsZS1jaGVjayB0aGUgYWN0dWFsIEhUTUwgZmlsZSBiZWNhdXNlIHNvbWV0aW1lcyB0aGluZ3MgbG9vayBkaWZmZXJlbnQgaW4gUlN0dWRpby4KPGJyLz4KCiFbXShmaWxlcy9wcmV2aWV3LnBuZykKClNvbWV0aGluZyB0byBjb25zaWRlciB3aGlsZSB5b3UgY3JlYXRlIHlvdXIgcGFnZSBpcyAqcmVhZGFiaWxpdHkqLiBUaGlzIG5vdCBvbmx5IGFwcGxpZXMgdG8gdGhlIGZpbmFsIGRvY3VtZW50IGJ1dCBhbHNvIHRoZSByYXcgUiBNYXJrZG93biBjb2RlIGl0c2VsZi4gVGhpbmsgYWJvdXQgc29tZW9uZSBkaWdnaW5nIHRocm91Z2ggeW91ciBjb2RlIHRvIGZpZ3VyZSBvdXQgaG93IHlvdSBkaWQgc29tZXRoaW5nLiBPciB0aGluayBhYm91dCB5b3Vyc2VsZiBjb21pbmcgYmFjayB0byB0aGUgY29kZSBhZnRlciBhIGZldyB5ZWFycy4gVGhlIGJldHRlciB5b3VyIGRvY3VtZW50IGlzIGZvcm1hdHRlZCwgdGhlIGVhc2llciBpdCB3aWxsIGJlIHRvIHVuZGVyc3RhbmQuIEluIGZ1dHVyZSBsZXNzb25zIHdlIHdpbGwgcmV0dXJuIHRvIHNvbWUgYmVzdCBwcmFjdGljZXMgYnV0IGZvciBub3cgcmVtZW1iZXIsIHBhcnQgb2Ygd2hhdCB3ZSBhcmUgZG9pbmcgaGVyZSBpcyBtYWtpbmcgeW91ciBzY2llbmNlIG1vcmUgKnRyYW5zcGFyZW50KiBhbmQgKnJlcHJvZHVjaWJsZSouIElmIHlvdXIgZG9jdW1lbnQgaXMgY29uZnVzaW5nIHRvIGZvbGxvdyB0aGVuIGl0IHNlcnZlcyBuZWl0aGVyIG9mIHRoZXNlIHB1cnBvc2VzLgoKIyMgQXNzaWdubWVudCAxOiBUaGUgQmFzaWNzCgpJbiB0aGUgZmlyc3QgYXNzaWdubWVudCwgeW91IHdpbGwgZW1wbG95IHNvbWUgYmFzaWMgdGVjaG5pcXVlcyB0byBjb250cm9sIHRoZSBsb29rIG9mIHlvdXIgZG9jdW1lbnQgYW5kIGhvdyBSIGNvZGUgY2h1bmtzIGFyZSByZW5kZXJlZC4gV2Ugd2lsbCBjb3ZlciBZQU1MIG1ldGFkYXRhIG1vZGlmaWNhdGlvbnMsIHNldHRpbmcgZ2xvYmFsIGNodW5rIG9wdGlvbnMsIGFuZCB3cml0aW5nIE1hcmtkb3duIGNvbnRlbnQuIFlvdSB3aWxsIGFsc28gbGVhcm4gYWJvdXQgdGVzdGluZyBSIGNvZGUgZmlyc3QgYmVmb3JlIHJlbmRlcmluZyB0aGUgZmluYWwgZG9jdW1lbnQuCgojIyMgMS4xIE1ha2UgYSBEb2N1bWVudAoKSWYgeW91IGhhdmUgbm90IGFscmVhZHkgZG9uZSBzbywgeW91ciBmaXJzdCB0YXNrIGlzIHRvIGNyZWF0ZSBhbiBSIE1hcmtkb3duIGRvY3VtZW50LiBPcGVuIFIgU3R1ZGlvIGFuZCBnbyB0byBgRmlsZSA+IE5ldyBGaWxlID4gUiBNYXJrZG93bmAuIEEgd2luZG93IHNob3VsZCBwb3AgdXAgd2hlcmUgeW91IGNhbiBmaWxsIGluIHRoZSBkZXRhaWxzLiBJdCBpcyBub3QgaW1wb3J0YW50IHdoYXQgeW91IHB1dCBoZXJlIHNpbmNlIHlvdSBjYW4gY2hhbmdlIGl0IGF0IGFueSB0aW1lLiBXaGF0IGlzIGltcG9ydGFudCBpcyB0aGF0ICoqRG9jdW1lbnQqKiBhbmQgKipIVE1MKiogYXJlIGJvdGggc2VsZWN0ZWQuIFdlIHdpbGwgY292ZXIgb3RoZXIgZG9jdW1lbnQgdHlwZXMgaW4gdGhlIGZ1dHVyZS4gSGl0IGBPa2AgYW5kIGZvbGxvdyB0aGUgc3RlcHMgaW4gdGhpcyBncmFwaGljLiBSZW1lbWJlciwgeW91IGRvIG5vdCBuZWVkIHRvIGFkZCBhIGZpbGUgZXh0ZW5zaW9uIHdoZW4geW91IHNhdmUgdGhlIGRvY3VtZW50LgoKPGJyLz4KCmBgYHtyIG1ha2Vfcm1kLCBlY2hvPUZBTFNFLCBjYWNoZT1UUlVFLCBmaWcuY2FwPSJCdWlsZGluZyB5b3VyIGluaXRpYWwgUiBNYXJrZG93biBkb2N1bWVudC4iIH0KaW5jbHVkZV9ncmFwaGljcygiZmlsZXMvbWFrZS1ybWQuZ2lmIikKYGBgCgo8YnIvPgoKT25jZSB5b3UgaGF2ZSBhIGRvY3VtZW50IGJ1aWx0IGFuZCBzYXZlZCwgdGhlcmUgc2hvdWxkIGJlIGEgYC5odG1sYCBmaWxlIGluIHlvdXIgd29ya2luZyBkaXJlY3RvcnkuIERvdWJsZS1jbGljayB0aGF0IGZpbGUtLS1pdCBzaG91bGQgb3BlbiBpbiB5b3VyIGRlZmF1bHQgYnJvd3Nlci4gRWFjaCB0aW1lIHlvdSByZS1rbml0IHRoZSBgLlJtZGAgZmlsZSwgeW91IGNhbiBqdXN0IHJlZnJlc2ggdGhlIGJyb3dzZXIgcGFnZSBvciBkb3VibGUtY2xpY2sgdGhlIGZpbGUgYWdhaW4uCgojIyMgMS4yIEFkZCBNYXJrZG93biBUZXh0CgpZb3VyIGZpcnN0IHRhc2sgaXMgdG8gYWRkIHNvbWUgY29udGVudCBhbmQgZm9ybWF0IHRoZSBjb250ZW50IHdpdGggTWFya2Rvd24uIFRoaXMgZG9lc24ndCBuZWVkIHRvIGJlIGFueXRoaW5nIGZhbmN5IHRvIHN0YXJ0LiBZb3UgY2FuIGVpdGhlciBhZGQgdGV4dCBhcyB5b3UgZ28gb3IgcGFzdGUgYSBsYXJnZSBhbW91bnQgb2YgdGV4dCBpbiBhdCBvbmNlLiBEZWFsZXJzIGNob2ljZS4gWW91IGNhbiB1c2UgdGhlIFtNYXJrZG93bl0oaHR0cHM6Ly9zdHJpLWNvbi5naXRodWIuaW8vZGF0YS1jdXJhdGlvbi8yMDIwLzAzLzI4L2xlc3Nvbi0wLyNtYXJrZG93bi0zKSBzZWN0aW9uIG9mIExlc3NvbiAwIG9yIHRoZSBbTWFya2Rvd25dKGh0dHBzOi8vc3RyaS1jb24uZ2l0aHViLmlvL2RhdGEtY3VyYXRpb24vcGFnZS9yZXNvdXJjZXMvI21hcmtkb3duKSBzZWN0aW9uIGZyb20gdGhlIFJlc291cmNlcyBwYWdlIGZvciByZWZlcmVuY2UuCgoxKSBBZGQgaGVhZGVycyB0byBnaXZlIHRoZSBkb2N1bWVudCBzdHJ1Y3R1cmUuIFVzZSBkaWZmZXJlbnQgaGVhZGVyIGxldmVscy4KMikgQWRkIGh5cGVybGlua3MuIFdlIHdpbGwgbGVhcm4gYWJvdXQgKmludGVybmFsKiBsaW5rcyBsYXRlci4gRm9yIG5vdywganVzdCBsaW5rIHRvIG91dHNpZGUgd2Vic2l0ZXMuCjMpIEFkZCBlbXBoYXNpcyBmb3JtYXR0aW5nIGxpa2UgYm9sZCwgaXRhbGljcywgYW5kIGJsb2NrIHRleHQuCjQpIE1peCBhbmQgbWF0Y2ggZm9ybWF0dGluZywgbGlrZSBtYWtlIGEgaHlwZXJsaW5rIGJvbGQgb3IgYWRkIGl0YWxpY3MgdG8gYmxvY2sgdGV4dC4KNSkgTWFrZSBhIGxpc3Qgb2YgaXRlbXMuCgojIyMgMS4zIE1vZGlmeSAmIFRlc3QgUiBDb2RlIENodW5rcwoKTm93IGl0IGlzIHRpbWUgdG8gZ2V0IHNvbWUgcHJhY3RpY2UgbW9kaWZ5aW5nIGNvZGUgY2h1bmsgb3B0aW9ucyBzbyB5b3UgY2FuIGdhaW4gbW9yZSBjb250cm9sIG92ZXIgdGhlIGJlaGF2aW9yIG9mIGNvZGUgYW5kIHJlc3VsdCBkaXNwbGF5LiBJZiB5b3UgaGF2ZSB5b3VyIG93biBSIGNvZGUgeW91IGFyZSBtb3JlIHRoYW4gd2VsY29tZSB0byB1c2UgaXQgaGVyZS4gSSB3aWxsIHVzZSB0aGUgZGVmYXVsdCBjb2RlIGNodW5rcyB0aGF0IHdlcmUgYWRkZWQgdG8gdGhlIGAuUm1kYCBmaWxlLiBQbGVhc2Ugc2VlIHRoZSBzZWN0aW9uIG9uIFtDaHVuayBzdHJ1Y3R1cmUgJiBvcHRpb25zXShodHRwczovL3N0cmktY29uLmdpdGh1Yi5pby9kYXRhLWN1cmF0aW9uLzIwMjAvMDQvMDkvbGVzc29uLTIvI2NodW5rLXN0cnVjdHVyZS1vcHRpb25zLTEpIGZyb20gTGVzc29uIDIgZm9yIG1vcmUgZGV0YWlscy4KCkhlcmUgYXJlIHRoZSB0d28gZGVmYXVsdCBjb2RlIGNodW5rcy4gQXMgeW91IGNhbiBzZWUsIGJvdGggaGF2ZSBuYW1lcyBhbmQgdGhlIHNlY29uZCBjaHVuayBoYXMgYSBzaW5nbGUgb3B0aW9uLgoKYGBgYApgYGB7ciBjYXJzfWByICcnYApzdW1tYXJ5KGNhcnMpCmBgYApgYGBgCgpgYGBgCmBgYHtyIHByZXNzdXJlLCBlY2hvPUZBTFNFfWByICcnYApwbG90KHByZXNzdXJlKQpgYGAKYGBgYAoKVGhlcmUgYXJlIG1hbnkgY29kZSBjaHVuayBvcHRpb25zIHlvdSBjYW4gY29udHJvbC4gV2hpY2ggb3B0aW9ucyB5b3UgdXNlIGFuZCBob3cgeW91IHNldCB0aGVtIHdpbGwgYmUgZGV0ZXJtaW5lZCBieSB5b3VyIG5lZWRzLiBUZXN0IHRoZSBiZWhhdmlvciBvZiB0aGUgZm9sbG93aW5nIG9wdGlvbnMgYnkgc2V0dGluZyBlYWNoIGVxdWFsIHRvIGVpdGhlciBgVFJVRWAgb3IgYEZBTFNFYC4gUmVuZGVyIHRoZSBkb2N1bWVudCBhbmQgc2VlIGlmIHlvdSBjYW4gZmlndXJlIG91dCB3aGF0IGNoYW5nZWQuIEVhY2ggb2YgdGhlc2UgaGFzIGEgZGVmYXVsdCB2YWx1ZSBzbyB5b3UgbWF5IG5vdCBzZWUgYSBjaGFuZ2UgdW50aWwgeW91IHNldCB0aGUgYWx0ZXJuYXRpdmUgdmFsdWUuCgoxKSBgZWNob2AKMikgYGNvbGxhcHNlYAozKSBgZXZhbGAKNCkgYHByb21wdGAKNSkgYGhpZ2hsaWdodGAKNikgYGluY2x1ZGVgCgpOZXh0LCBpdCBpcyBhIHJlYWxseSBnb29kIGhhYml0IHRvIGNoZWNrIGNvZGUgY2h1bmtzIGFzIHlvdSBhZGQgdGhlbS4gVGhpcyB3aWxsIGVuc3VyZSB0aGF0IGVhY2ggY2h1bmsgd29ya3MsIG1ha2luZyBpdCBlYXNpZXIgdG8gdHJhY2sgZG93biBwcm9ibGVtcy4gSWYgeW91IHJlZmVyIHRvIHRoZSBmaXJzdCBpbWFnZSBvbiB0aGlzIHBhZ2UsIHlvdSBjYW4geW91IGhhdmUgb3B0aW9ucyBmb3IgKipDaHVuayBPdXRwdXQqKi0tLSpJbmxpbmUqIGFuZCAqQ29uc29sZSouIFRoaXMgY29udHJvbHMgd2hlcmUgdGhlIG91dHB1dCBpcyBkaXNwbGF5ZWQuIExldCdzIHRha2UgYSBxdWljayBsb29rIGF0IGEgY29kZSBjaHVuayBpbiBSU3R1ZGlvIGFuZCBzZWUgaG93IHlvdSB0ZXN0IGNodW5rcyBiZWZvcmUgcmVuZGVyaW5nLgoKIVtdKGZpbGVzL3J1bi1jaHVuay5wbmcpCgpUYWtlIGEgbG9vayBhdCB0aGUgdG9vbCBiYXIgb24gdGhlIGZhciByaWdodC4gKipPcHRpb24gMSoqIGlzIGEgZHJvcCBkb3duIG1lbnUgdGhhdCBnaXZlcyB5b3UgYW4gYWx0ZXJuYXRpdmUgd2F5IHRvIHNldCBjb2RlIGNodW5rIG9wdGlvbnMuICoqT3B0aW9uIDIqKiB3aWxsICpSdW4gYWxsIENvZGUgQ2h1bmtzIEFib3ZlKiBtZWFuaW5nIHRoYXQgUlN0dWRpbyB3aWxsIHJ1biBhbGwgY29kZSBjaHVua3MgYWJvdmUgdGhlIGN1cnJlbnQgY2h1bmsgYnV0IG5vdCB0aGUgY3VycmVudCBjaHVuayBpdHNlbGYuIEFuZCAqKk9wdGlvbiAzKiogd2lsbCAqUnVuIHRoZSBDdXJyZW50IENodW5rKi4gSW5jaWRlbnRhbGx5LCBpZiB5b3UgZG8gbm90IHNlZSB0aGVzZSBvcHRpb25zIGl0IG1lYW5zIHNvbWV0aGluZyBpcyB3cm9uZyB3aXRoIHRoZSBjaHVuay4KCkdvIGFoZWFkIGFuZCBydW4gdGhlIGNodW5rLgoKIyMjIDEuNCBNb2RpZnkgWUFNTCBNZXRhZGF0YQoKWW91IGxhc3QgdGFzayBpcyB0byBtb2RpZnkgdGhlIFlBTUwgaGVhZGVyIHRvIHN1aXQgeW91ciBuZWVkcyBhbmQgdGFzdGVzLiBJIHdvdWxkIGxpa2UgeW91IHRvIGV4cGVyaW1lbnQgd2l0aCBkaWZmZXJlbnQgb3B0aW9ucyBhbmQgc2V0dGluZ3MgdG8gc2VlIHdoYXQgaGFwcGVucyBpbiB0aGUgZmluYWwgZG9jdW1lbnQuCgoxKSBSdW4gYD9ybWFya2Rvd246Omh0bWxfZG9jdW1lbnRgIG9yIGA/aHRtbF9kb2N1bWVudGAgaW4gdGhlIENvbnNvbGUgdG8gc2VlIHRoZSBoZWFkZXIgb3B0aW9ucyBmb3IgYW4gSFRNTCBkb2N1bWVudC4KMikgQWRkIGEgdGFibGUgb2YgY29udGVudHMgYW5kIGluY2x1ZGUgb3B0aW9ucyB0aGF0IG1vZGlmeSB0aGUgYmVoYXZpb3Igb2YgdGhlIHRhYmxlIG9mIGNvbnRlbnRzLgozKSBBZGQgdGhlIG9wdGlvbiB0byBrZWVwIHRoZSBNYXJrZG93biBkb2N1bWVudC4gVGhpcyB3aWxsIHNhdmUgYSBgLm1kYCBjb3B5IG9mIHlvdXIgZmlsZS4KNCkgT3BlbiB0aGUgYC5tZGAgZmlsZSBpbiBhIHRleHQgZWRpdG9yLiBUaGlzIGlzIHRoZSBvdXRwdXQgZnJvbSBga25pdHJgLS0tYWZ0ZXIgYWxsIFIgY29kZSBoYXMgYmVlbiBwcm9jZXNzZWQtLS1hbmQgd2hhdCBQYW5Eb2MgdXNlcyB0byBnZW5lcmF0ZSBhbiBIVE1MIGZpbGUuIEtlZXAgdGhpcyBmaWxlIG9wZW4gYXMgeW91IGJ1aWxkIHlvdXIgZG9jdW1lbnQuIFBheSBhdHRlbnRpb24gdG8gaG93IHlvdXIgUiBjb2RlIGlzIGNvbnZlcnRlZCB0byBNYXJrZG93biBzeW50YXguCjUpIENoYW5nZSB0aGUgdGhlbWUuIE9wdGlvbnMgYXJlIGxpc3RlZCBvbiB0aGUgKkNvbnZlcnQgdG8gYW4gSFRNTCBkb2N1bWVudCogaGVscCBwYWdlIHlvdSBvcGVuZWQgaW4gUlN0dWRpby4gVHJ5IGEgZmV3IG9wdGlvbnMgYW5kIHNlZSB3aGF0IGhhcHBlbnMuCjYpIENoYW5nZSB0aGUgY29kZSBoaWdobGlnaHQgb3B0aW9uLiBUaGVzZSB0b28gYXJlIGxpc3RlZCBvbiB0aGUgaGVscCBwYWdlLiBUcnkgYSBmZXcgb3B0aW9ucyBhbmQgc2VlIHdoYXQgaGFwcGVucy4KCiMjIEFzc2lnbm1lbnQgMjogVGFibGVzCgpJbiB0aGlzIGFzc2lnbm1lbnQsIHlvdSB3aWxsIGV4cGxvcmUgZGlmZmVyZW50IG1ldGhvZHMgb2YgaW5jb3Jwb3JhdGluZyB0YWJsZXMgaW4geW91ciBkb2N1bWVudC4gVGhlIGNob2ljZSBvZiBtZXRob2QgZGVwZW5kcyBvbiAqKmEqKikgdGhlIHR5cGUgb2YgZGF0YSwgKipiKiopIHRoZSBhbW91bnQgb2YgZGF0YSwgYW5kICoqYyoqKSB0aGUgZGVzaXJlZCBvdXRwdXQuIEkgd2lsbCBjb3ZlciBhIGZldyB0b29scyBmb3IgY3JlYXRpbmcgdGFibGVzIGJ1dCBwbGVhc2Ugbm90ZSB0aGVyZSBhcmUgW21hbnkgb3B0aW9uc10oaHR0cHM6Ly9yZm9ydGhlcmVzdG9mdXMuY29tLzIwMTkvMTEvaG93LXRvLW1ha2UtYmVhdXRpZnVsLXRhYmxlcy1pbi1yLykgb3V0IHRoZXJlLCBzbyBsb29rIGFyb3VuZCBhbmQgbGV0IHVzIGtub3cgaWYgeW91IGZpbmQgYSB0b29sIHlvdSBsaWtlLgoKRm9yIGVhY2ggZXhhbXBsZSwgSSB3aWxsIHVzZSB0aGUgYG10Y2Fyc2AgZGF0YSBzZXQgZnJvbSB0aGUgYGRhdGFzZXRzYCBwYWNrYWdlLiBUaGUgYG10Y2Fyc2AgZGF0YSBzZXQgaGFzIGByIG5yb3cobXRjYXJzKWAgcm93cyBhbmQgYHIgbmNvbChtdGNhcnMpYCBjb2x1bW5zLiBGZWVsIGZyZWUgdG8gbG9hZCB5b3VyIG93biBkYXRhIHRhYmxlIG9yIHVzZSB0aGUgYG10Y2Fyc2AgZGF0YSBzZXQuCgojIyMgVG9vbHMKCllvdSB3aWxsIHVzZSBmb3VyIGRpZmZlcmVudCB0b29scyBpbiB0aGlzIGFzc2lnbm1lbnQgZm9yIG1ha2luZyB0YWJsZXMuIEhlcmUgaXMgYSBzdW1tYXJ5IHRhYmxlIG9mIG9mIGVhY2ggdG9vbC4gCgp8IFRhYmxlIHR5cGUgICAgICAgICAgICAgICAgICAgIHwgVGFibGUgc2l6ZSAgICAgICB8ICBGb3JtYXR0aW5nIE9wdGlvbnMgIHwgU2tpbGwgTGV2ZWwgICAgICB8CnwtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tfDotLS0tLS0tLS0tLS0tLS0tOnw6LS0tLS0tLS0tLS0tLS0tLS0tLS06fDotLS0tLS0tLS0tLS0tLS0tOnwKfCBgbWFya2Rvd25gICAgICAgICAgICAgICAgICAgICB8IHNtYWxsICAgICAgICAgICAgfCBtaW5pbWFsICAgICAgICAgICAgICB8IGJlZ2lubmVyICAgICAgICAgfAp8IGBybWFya2Rvd246OnBhZ2VkX3RhYmxlYCAgICAgIHwgbGFyZ2UgICAgICAgICAgICB8IG1pbmltYWwgICAgICAgICAgICAgIHwgYmVnaW5uZXIgICAgICAgICB8CnwgYGtuaXRyOjprYWJsZWAgKyBga2FibGVFeHRyYWAgfCBzbWFsbCAgICAgICAgICAgIHwgZXh0ZW5zaXZlICAgICAgICAgICAgfCBpbnRlcm1lZGlhdGUgICAgIHwKfCBgRFRgICsgYERhdGFUYWJsZXNgICAgICAgICAgICB8IGxhcmdlICAgICAgICAgICAgfCBleHRlbnNpdmUgICAgICAgICAgICB8IGFkdmFuY2VkICAgICAgICAgfApUYWJsZTogKlRhYmxlIHR5cGVzIGFuZCByZWNvbW1lbmRlZCB1c2VzLioKCjxici8+CgojIyMgMi4xIE1hcmtkb3duCgpUaGUgc2ltcGxlc3QgbWV0aG9kIG9mIGJ1aWxkaW5nIGEgdGFibGUgaXMgd2l0aCBNYXJrZG93biBzeW50YXguIFRoaXMgaXMgYSBuaWNlIG9wdGlvbiBiZWNhdXNlIHlvdSBjYW4gaGFyZCBjb2RlIHRoZSB0YWJsZSByaWdodCBpbnRvIHRoZSBkb2N1bWVudC0tLW5vIG5lZWQgdG8gaW5zdGFsbCBhbmQgbG9hZCBsaWJyYXJpZXMgb3Igd3JpdGUgY29kZSBjaHVua3MtLS1hbmQgaXQgaXMgZWFzeSB0byBpbXBsZW1lbnQuIFRoZSBkb3duc2lkZSBpcyB0aGVyZSBpcyBtaW5pbWFsIGZ1bmN0aW9uYWxpdHkgYXZhaWxhYmxlIGluIGEgTWFya2Rvd24gdGFibGUuCgpNYXJrZG93biBkb2VzIG5vdCB3b3JrIHdlbGwgZm9yIGxhcmdlIHRhYmxlcy4gU28gSSB3aWxsIGZpcnN0IGdyYWIgYSBzdWJzZXQgb2YgYG10Y2Fyc2AsIHNwZWNpZmljYWxseSB0aGUgZmlyc3QgNCByb3dzIGFuZCAzIGNvbHVtbnMuIEluIG15IGNvZGUgY2h1bmsgSSBhZGQgdGhlIGNodW5rIG9wdGlvbiBgY29tbWVudD0iImAuIFRoaXMgcHJldmVudHMga25pdCBmcm9tIGFwcGVuZGluZyBhIHN0cmluZyAoZGVmYXVsdCBpcyBgIyNgKSB0byB0aGUgc3RhcnQgb2YgZWFjaCBsaW5lIG9mIHJlc3VsdHMgaW4gdGhlIGZpbmFsIGRvY3VtZW50LgoKYGBge3IgbXRjYXJzX3N1YiwgY29tbWVudD0iIn0KbXRjYXJzX3N1YiA8LSBtdGNhcnNbMTo0LDE6M10KbXRjYXJzX3N1YgpgYGAKCjxici8+CgoqSW5jaWRlbnRhbGx5LCB0aGUgcmVzdWx0cyBib3ggYWJvdmUgaXMgdGVjaG5pY2FsbHkgdGhlIHNpbXBsZXN0IHRhYmxlIHlvdSBjYW4gbWFrZSwgZWl0aGVyIGJ5IGNhbGxpbmcgdGhlIGRhdGEgZnJhbWUgYG10Y2Fyc19zdWJgIGRpcmVjdGx5IG9yIHJ1bm5pbmcgYHByaW50LmRhdGEuZnJhbWUobXRjYXJzX3N1YilgLioKCkFueXdheSwgcnVuIHRoaXMgY29kZSBjaHVuaywgY29weSB0aGUgcmVzdWx0cywgYW5kIG1ha2UgYSBNYXJrZG93biB0YWJsZS4gWW91IGNhbiBlaXRoZXIgcnVuIHRoZSBjaHVuayBpbiBSU3R1ZGlvIHdpdGhvdXQgcmVuZGVyaW5nIHRoZSBkb2N1bWVudCAoZGVzY3JpYmVkIGFib3ZlKSBvciByZW5kZXIgdGhlIGRvY3VtZW50IGFuZCBjb3B5IHRoZSByZXN1bHRzIGZyb20gSFRNTCBwYWdlLiBJIGFkZGVkIGEgaGVhZGVyIHRvIHRoZSBmaXJzdCBjb2x1bW4uIEFuZCBoZXJlIGlzIHRoZSBNYXJrZG93biB0YWJsZS4KCjxici8+Cgp8IG1vZGVsICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgIG1wZyAgIHwgIGN5bCB8ICBkaXNwICAgICB8Cnw6LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tfDotLS0tLS06fDotLS0tOnwtLS0tLS0tLS0tOnwKfCBbTWF6ZGEgUlg0XShodHRwczovL3Njby53aWtpcGVkaWEub3JnL3dpa2kvTWF6ZGFfUlgtNCkgICAgICAgICAgICB8ICoyMS4wKiB8ICoqNioqfCAgICAxNjAgICAgfAp8IGBNYXpkYSBSWDQgV2FnYCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgKjIxLjAqIHwgICA2ICB8ICAgIDE2MCAgICB8CnwgW0RhdHN1biA3MTBdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL05pc3Nhbl9WaW9sZXQjNzEwKSAgICAgfCAqMjIuOCogfCAgIDQgIHwgICAgMTA4ICAgIHwKfCBbSG9ybmV0IDQgRHJpdmVdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0FNQ19Ib3JuZXQpICAgICAgICB8IDIxLjQgICB8ICAgNiAgfCAgKioyNTgqKiAgfApUYWJsZTogICpEZW1vbnN0cmF0aW9uIG9mIHRoZSBvdXRwdXQgZnJvbSBgcGlwZV90YWJsZXNgIE1hcmtkb3duIHN5bnRheC4qCgo8YnIvPgoKU2luY2UgdGhpcyBpcyBhIE1hcmtkb3duIHRhYmxlLCB5b3UgY2FuIGFkZCBhZGRpdGlvbmFsIE1hcmtkb3duIHN5bnRheCBmb3IgZm9ybWF0dGluZy4gU2VlIGlmIHlvdSBjYW4gZmlndXJlIG91dCB3aGF0IHN5bnRheCBJIGFkZGVkIHRvIG15IHRhYmxlIGFuZCBhZGQgc29tZSB0byB5b3VyIHRhYmxlLiBBbHNvIGNoZWNrIG91dCB0aGUgKlRhYmxlcyogc2VjdGlvbiBvZiBbUGFuRG9jIFVzZXIncyBHdWlkZV0oaHR0cHM6Ly9wYW5kb2Mub3JnL01BTlVBTC5odG1sI3RhYmxlcykgZm9yIG90aGVyIE1hcmtkb3duIHRhYmxlIG9wdGlvbnMsIGluY2x1ZGluZyBob3cgdG8gYWRkIGEgY2FwdGlvbi4gSW4gYWRkaXRpb24gdG8gYHBpcGVfdGFibGVzYCwgeW91IGNhbiBjcmVhdGUgYG11bHRpbGluZV90YWJsZXNgIGBncmlkX3RhYmxlc2AsIGFuZCBgc2ltcGxlX3RhYmxlc2AuCgpTb21ldGhpbmcgdG8gbm90aWNlIGlzIHRoYXQgdGhlIE1hcmtkb3duIHRhYmxlIHNwYW5zIHRoZSBlbnRpcmUgd2lkdGggb2YgdGhlIHBhZ2UtLS1ldmVuIHRob3VnaCBpdCBkb2VzIG5vdCBuZWVkIGFsbCBvZiB0aGF0IHNwYWNlLiBBcyBmYXIgYXMgSSBrbm93LCB0aGVyZSBpcyBubyB3YXkgdG8gY29udHJvbCB0aGlzIGJlaGF2aW9yIHdpdGhvdXQgYWRkaW5nIGFkZGl0aW9uYWwgSFRNTCBmb3JtYXR0aW5nLgoKPiAqKlJlY29tbWVuZGF0aW9uKiogVXNlIGBNYXJrZG93bmAgZm9yIHNtYWxsLCBzaW1wbGUgdGFibGVzIHdoZXJlIHN0eWxpbmcgaXMgbm90IGEgY29uY2Vybi4KCiMjIyAyLjIgUiBNYXJrZG93biBQYWdlZCBUYWJsZXMKCldpdGggbGFyZ2VyIHRhYmxlcywgaXQgbWF5IG5vdCBiZSBwcmFjdGljYWwgdG8gZGlzcGxheSB0aGUgZnVsbCB0YWJsZSBpbmxpbmUuIFNvIHdlIG5lZWQgYSB3YXkgdG8gc2hyaW5rIGEgbGFyZ2UgdGFibGUgc28gaXQgbG9va3MgZ29vZCB3aGlsZSBzdGlsbCBhbGxvd2luZyBhY2Nlc3MgdG8gdGhlIGZ1bGwgdGFibGUuCgpUaGUgbmV4dCB0eXBlIG9mIHRhYmxlIEkgd2FudCB5b3UgdG8gdHJ5IGFyZSBQYWdlZCBUYWJsZXMuIFIgTWFya2Rvd24gY29tZXMgd2l0aCBpdHMgb3duIGJ1aWx0IGluIHRhYmxlIGZ1bmN0aW9uIGNhbGxlZCBgcGFnZWRfdGFibGVgLiBUaGUgYHBhZ2VkX3RhYmxlYCBmdW5jdGlvbiBhbGxvd3MgcGFnaW5hdGlvbiBvZiByb3dzIGFuZCBjb2x1bW5zIG1ha2luZyBpdCBwb3NzaWJsZSB0byByZW5kZXIgYSBsYXJnZSB0YWJsZSBpbiBhIHNtYWxsIHNwYWNlLgoKSXQgaXMgZWFzeSB0byBjb2RlIGBwYWdlZF90YWJsZWAgYnV0IHRoYXQgZWFzZSBjb21lcyB3aXRoIGEgc21hbGwgcHJpY2UtLS1saW1pdGVkIGZ1bmN0aW9uYWxpdHkuIEhlcmUgYXJlIHRoZSBvcHRpb25zIHlvdSBkbyBoYXZlIHdpdGggYHBhZ2VkX3RhYmxlYCBmdW5jdGlvbi4KCnwgT3B0aW9uICAgICAgICAgICB8IERlc2NyaXB0aW9uICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfAp8LS0tLS0tLS0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLXwKfCBgcm93cy5wcmludGAgICAgIHwgTWF4aW11bSByb3dzIHRvIHByaW50IHBlciBwYWdlLiAgICAgICAgICAgICAgICB8CnwgYG1heC5wcmludGAgICAgICB8IE1heGltdW0gcm93cyBpbiB0aGUgdGFibGUgKGRlZmF1bHRzIHRvIDEwMDApLiAgfAp8IGBjb2xzLnByaW50YCAgICAgfCBNYXhpbXVtIGNvbHVtbnMgaW4gdGhlIHRhYmxlIChkZWZhdWx0cyB0byAxMCkuIHwKfCBgcm93bmFtZXMucHJpbnRgIHwgUHJpbnQgcm93IG5hbWVzIGFzIHBhcnQgb2YgdGhlIHRhYmxlLiAgICAgICAgICB8ClRhYmxlOiAqQSBNYXJrZG93biB0YWJsZSBsaXN0aW5nIHRoZSBPcHRpb25zIGZvciB0aGUgYHBhZ2VkX3RhYmxlYCBmdW5jdGlvbi4gKgoKKioqQSBxdWljayBzaWRlIG5vdGUqKiouIFlvdSBhY3R1YWxseSBuZWVkIHRvIGxvYWQgdGhlIGBybWFya2Rvd25gIHBhY2thZ2UgZm9yIGBwYWdlZF90YWJsZWAgdG8gd29yay4gQW55d2F5LCB0aGlzIGlzIGEgZ29vZCB0aW1lIHRvIHJldHVybiB0byB0aGUgZmlyc3QgY29kZSBjaHVuayBpbiB5b3VyIGAuUm1kYCBmaWxlLS0tdGhlIGNodW5rIGNhbGxlZCBgc2V0dXBgIHRoYXQgUiBNYXJrZG93biBhZGRlZCBieSBkZWZhdWx0LgoKSSBsaWtlIHRvIHVzZSB0aGlzIGNodW5rIHRvIGxvYWQgYWxsIG9mIHRoZSBwYWNrYWdlcyBJIG5lZWQgZm9yIG15IGRvY3VtZW50LiBVc2luZyBhIHNpbmdsZSBjaHVuayBmb3IgYWxsIG9mIG15IHBhY2thZ2VzIGhlbHBzIG1lIGtlZXAgbXkgZG9jdW1lbnQgb3JnYW5pemVkLiBOb3RpY2UgdGhlIGBzZXR1cGAgY2h1bmsgaGFzIHRoZSBvcHRpb24gYGluY2x1ZGU9RkFMU0VgLiBUaGlzIHByZXZlbnRzIHRoZSBjb250ZW50IG9mIHRoZSBjaHVuayBmcm9tIGFwcGVhcmluZyBpbiB0aGUgZmluYWwgZG9jdW1lbnQsIHdoaWNoIGZvciBtZSBpcyBtb3JlIHN0eWxpc3RpY2FsbHkgYXBwZWFsaW5nLiAgSSBjYW4gYWRkIGEgYHNlc3Npb25JbmZvKClgIGNodW5rIGF0IHRoZSBlbmQgb2YgbXkgZG9jdW1lbnQgdG8gcmVwb3J0IGFsbCBvZiB0aGUgcGFja2FnZXMgc28gdGhpcyBpbmZvcm1hdGlvbiBpcyBhdmFpbGFibGUgdG8gdGhlIHJlYWRlci4gV2Ugd2lsbCBjb3ZlciBgc2Vzc2lvbkluZm8oKWAgd2hlbiB3ZSBnZXQgaW50byBtb3JlIGRlcHRoIG9uIHRoZSBzdWJqZWN0IG9mICpyZXByb2R1Y2libGUqLiBJZiB5b3UgZG8gbm90IHdhbnQgdG8gbG9hZCB0aGUgbGlicmFyeSB5b3UgY2FuIHJ1biB0aGUgY29tbWFuZCBsaWtlIHRoaXM6IGBybWFya2Rvd246OnBhZ2VkX3RhYmxlKClgLgoKKioqT0ssIGJhY2sgdG8gdGhlIHRhYmxlKioqLiBOb3cgSSBjYW4gY3JlYXRlIGEgdGFibGUgb2YgYG10Y2Fyc2Agd2l0aCB0aGUgYHBhZ2VkX3RhYmxlYCBmdW5jdGlvbiBhbmQgdXNlIGFuIG9wdGlvbiB0byBsaW1pdCB0aGUgbnVtYmVyIG9mIHByaW50ZWQgcm93cyB0byBgNWAgZm9yIGVhY2ggcGFnZS4gSSB1c2VkIGBlY2hvPUZBTFNFYCBpbiBteSBjb2RlIGNodW5rIHRvIGhpZGUgdGhlIGNvZGUgOikuIEJ5IG5vdyB5b3Ugc2hvdWxkIGtub3cgd2hlcmUgdG8gbG9vayBmb3IgYSBzb2x1dGlvbi4KCjxici8+CgpgYGB7ciBtdGNhcnNfcGFnZWQsIGVjaG89RkFMU0UsIGZpZy5jYXA9InN0dWZmIn0KcGFnZWRfdGFibGUobXRjYXJzLCBvcHRpb25zID0gbGlzdChyb3dzLnByaW50ID0gNSkpCmBgYAoKTm90aWNlIHRoYXQgZm9yIGVhY2ggY29sdW1uLCB0aGUgY29sdW1uICpjbGFzcyogaXMgcHJpbnRlZCBiZWxvdyB0aGUgbmFtZSAodGV4dCBlbmNsb3NlZCBpbiA8ID4pLiBUaGlzIGlzIGlycml0YXRpbmcgYW5kIHJlbGF0ZWQgdG8gcHJpbnRpbmcgYSB0YWJsZSBmcm9tIGEgYnVpbHQtaW4gZGF0YSBmcmFtZS4gSSBoYXZlIG5vIGlkZWEgaG93IHRvIGZpeCB0aGlzICh3aXRoaW4gdGhlIGNvbmZpbmVzIG9mIFIgTWFya2Rvd24pIGJ1dCBJIHdpbGwgd29yayBvbiBhIHNvbHV0aW9uLgoKPiAqKlJlY29tbWVuZGF0aW9uKiogVXNlIGBwYWdlZF90YWJsZWAgZm9yIGxhcmdlIHRhYmxlcyB3aGVyZSBleHRlbnNpdmUgc3R5bGluZyBpcyBub3QgYSBjb25jZXJuLgoKIyMjIDIuMyBLYWJsZSBUYWJsZXMKCktuaXRyIGNvbWVzIHdpdGggaXRzIG93biB0b29sIGZvciByZW5kZXJpbmcgc2ltcGxlIHRhYmxlcyBjYWxsZWQgYGthYmxlYC4gVGhlIGRvY3VtZW50YXRpb24gZm9yIGBrYWJsZWAgY2FuIGJlIGZvdW5kIFtoZXJlXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMva2FibGVFeHRyYS9pbmRleC5odG1sKSBvciBieSBydW5uaW5nIGA/a25pdHI6OmthYmxlKClgIGluIHRoZSBDb25zb2xlLiBCeSBpdHNlbGYsIGthYmxlICBjb21lcyB3aXRoICphbG1vc3Qgbm8gb3B0aW9ucyouIFdlIGNhbiBleHRlbmQgaXRzIGZ1bmN0aW9uYWxpdHkgd2l0aCB0aGUgYGthYmxlRXh0cmFgIHBhY2thZ2UgYW5kIHBpcGluZyBzeW50YXggZnJvbSBgbWFncml0dHJgLiBUaGUgZmVhdHVyZXMgb2YgYGthYmxlRXh0cmFgICBhcmUgZXh0ZW5zaXZlIGFuZCBJIHdpbGwgb25seSB0b3VjaCBvbiBhIGZldyBoZXJlLiBUaGUgZG9jdW1lbnRhdGlvbiBmb3IgYGthYmxlRXh0cmFgIGNhbiBiZSBmb3VuZCBbaGVyZV0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL2thYmxlRXh0cmEvaW5kZXguaHRtbCkgb3IgYnkgcnVubmluZyBgP2thYmxlRXh0cmFgIGluIHRoZSBDb25zb2xlIGFmdGVyIHRoZSBwYWNrYWdlIGhhcyBiZWVuIGluc3RhbGxlZCBhbmQgbG9hZGVkLgoKPiBJIGhpZ2hseSByZWNvbW1lbmQgeW91IFtsZWFybiBob3cgdG8gdXNlIHRoZXNlIHBhY2thZ2VzXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMva2FibGVFeHRyYS92aWduZXR0ZXMvYXdlc29tZV90YWJsZV9pbl9odG1sLmh0bWwpIGZvciBtYWtpbmcgdGFibGVzLgoKQWdhaW4sIHlvdSB3aWxsIG5lZWQgdG8gbG9hZCBga2FibGVFeHRyYWAgYW5kIGVpdGhlciBsb2FkIHRoZSBga25pdHJgIHBhY2thZ2Ugb3IgcnVuIHRoZSBjb21tYW5kIGxpa2UgdGhpczogYGtuaXRyOjprYWJsZSgpYC4KCkZpcnN0LCBsZXTigJlzIGxvb2sgYXQgdGhlIGRlZmF1bHQgYGthYmxlYCB0YWJsZSBvdXRwdXQuIFdlIHdpbGwgdXNlIHRoZSBoZWFkIG9mIHRoZSBgbXRjYXJzYCBkYXRhIHNldC4KCjxici8+CgpgYGB7ciBrYWJsZV9kZWZhdWx0fQprYWJsZShoZWFkKG10Y2FycyksIGNhcHRpb24gPSAiKldvdywgdGhpcyB0YWJsZSBsb29rcyB0ZXJyaWJsZS4qIikKYGBgCgo8YnIvPgoKSWYgd2UgdHJpZWQgdG8gcmVuZGVyIHRoZSBlbnRpcmUgdGFibGUgYnkgb21pdHRpbmcgYGhlYWRgLCB3ZSB3b3VsZCBqdXN0IGdldCBhIGxvbmcsIGNyYXBweSB0YWJsZSBpbiBvdXIgZG9jdW1lbnQuIE5vdCBjb29sLiBMZXRzIHNlZSBpZiB3ZSBjYW4gamF6eiB0aGlzIHVwIGEgYml0IHdpdGggYGthYmxlRXh0cmFgLgoKYGBge3Iga2FibGVfamF6en0Ka2FibGUoaGVhZChtdGNhcnMpLCBjYXB0aW9uID0gIipUaGlzIHRhYmxlIGxvb2tzIGJldHRlcioiKSAlPiUKICBrYWJsZV9zdHlsaW5nKCkKCmBgYAoKSGVyZSBJIHVzZWQgdGhlIFtwaXBlIG9wZXJhdG9yXShodHRwczovL3JpcHR1dG9yaWFsLmNvbS9yL3RvcGljLzY1Mi9waXBlLW9wZXJhdG9ycy0tLS0tLWFuZC1vdGhlcnMtKSAoYCU+JWApIHRvIHBhc3MgdGhlIHJlc3VsdHMgb2YgYGthYmxlYCB0byB0aGUgZnVuY3Rpb24gYGthYmxlX3N0eWxpbmdgLS0tYSBwYXJ0IG9mIHRoZSBga2FibGVFeHRyYWAgcGFja2FnZS4gQnkgcnVubmluZyAgYGthYmxlX3N0eWxpbmdgICphcyBpcyosIEkgYW0gdXNpbmcgZGVmYXVsdHMgZm9yIGFsbCBvZiB0aGUgb3B0aW9ucy4KCj4gVGhlIHBpcGUgb3BlcmF0b3IgaXMgYSBwb3dlcmZ1bCB0b29sIHdvcnRoIGxlYXJuaW5nLgoKQmFjayB0byB0aGUgdGFibGUuIEl0IGNlcnRhaW5seSBsb29rcyBiZXR0ZXIgdGhhbiB0aGUgZGVmYXVsdCBga2FibGVgIHZlcnNpb24gYnV0IHdlIGFyZSBtaXNzaW5nIHRoZSBhYmlsaXR5IHRvICpwYWdlKiB0aGUgdGFibGUuIEkgd291bGQgbGlrZSB5b3UgdG8gcnVuIHRoZXNlIHR3byBjb21tYW5kcyBhbmQgbG9vayBhdCB0aGUgb3V0cHV0LgoKVGhpcyBjb21tYW5kIHdpbGwgaW5jbHVkZSB0aGUgd2hvbGUgdGFibGUuCgpgYGAKa2FibGUobXRjYXJzKSAlPiUKICBrYWJsZV9zdHlsaW5nKCkKYGBgCgpBbmQgdGhpcyBjb21tYW5kIHdpbGwgdHJhbnNwb3NlIHRoZSB0YWJsZSAoc3dhcCByb3dzIGFuZCBjb2x1bW5zKSB1c2luZyB0aGUgdHJhbnNwb3NlIChgdGApIGZ1bmN0aW9uLiBSZW1lbWJlciwgYG10Y2Fyc2AgaGFzIGByIG5yb3cobXRjYXJzKWAgcm93cyBhbmQgYHIgbmNvbChtdGNhcnMpYCBjb2x1bW5zIGJ1dCB3aGVuIHlvdSB0cmFuc3Bvc2UgdGhlIHRhYmxlLCBpdCBoYXMgYHIgbnJvdyh0KG10Y2FycykpYCByb3dzIGFuZCBgciBuY29sKHQobXRjYXJzKSlgIGNvbHVtbnMuIFNvIGl0IGlzIHJlYWxseSB3aWRlIGluIHRoZSB0cmFuc3Bvc2VkIHN0YXRlLgoKYGBgCmthYmxlKGhlYWQodChtdGNhcnMpKSkgJT4lCiAga2FibGVfc3R5bGluZygpCmBgYAoKSSBob3BlIHlvdSBhZ3JlZSB0aGF0IG5laXRoZXIgb2YgdGhlc2UgdGFibGVzIGFyZSBhY2NlcHRhYmxlLCBlc3BlY2lhbGx5IHRoZSBzZWNvbmQgb25lLiBVbmZvcnR1bmF0ZWx5LCB0aGUgYGthYmxlRXh0cmFgIHBhY2thZ2UgZG9lcyBub3QgY29tZSB3aXRoIGFuIG9wdGlvbiB0byBhZGQgcGFnaW5hdGlvbi4gWW91IGNhbiBob3dldmVyIHB1dCB0aGUgdGFibGUgaW4gYSBmaXhlZC1oZWlnaHQsIGZpeGVkLXdpZHRoIChvciBib3RoKSBib3gsIGFuZCBtYWtlIGl0IHNjcm9sbGFibGUuIFdlIGNhbiBkbyB0aGlzIGJ5IHVzaW5nIGEgcGlwZSBvcGVyYXRvciBhbmQgdGhlIGBzY3JvbGxfYm94YCBmdW5jdGlvbi4gV2hpbGUgd2UgYXJlIGF0IGl0LCBsZXRzIGFsc28gYWRkIHR3ZWFrIHNvbWUgb3B0aW9ucyBpbiBga2FibGVfc3R5bGluZ2AgdG8gbWFrZSBhIG1vcmUgaGFuZHNvbWUgdGFibGUuCgpgYGB7ciBrYWJsZV9zY3JvbGx9CmthYmxlKHQobXRjYXJzKSwgY2FwdGlvbiA9ICIqU2Nyb2xsYWJsZSBrYWJsZSB0YWJsZS4qIikgJT4lCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJjb25kZW5zZWQiLCAicmVzcG9uc2l2ZSIpKSAlPiUKICBzY3JvbGxfYm94KHdpZHRoID0gIjEwMCUiLCBoZWlnaHQgPSAiMzAwcHgiKQpgYGAKCjxici8+CgpGb3IgdGhlIGBzY3JvbGxfYm94YCBmdW5jdGlvbiBJIHNldCB0aGUgYHdpZHRoID0gIjEwMCUiYCByYXRoZXIgdGhhbiBzcGVjaWZ5aW5nIGEgZGltZW5zaW9uLiBUaGlzIGVuc3VyZXMgdGhlIGJveCB3aWxsIGFsd2F5cyBiZSB0aGUgd2lkdGggb2YgdGhlIHBhZ2Ugbm8gbWF0dGVyIGhvdyBzbWFsbCB0aGUgd2luZG93IGlzLgoKRXZlbiB0aG91Z2ggeW91IGNhbm5vdCBtYWtlIGEgcGFnZWQgdGFibGUgd2l0aCBga2FibGVgLCB0aGVyZSBhcmUgIG1hbnkgc3R5bGluZyBvcHRpb25zIGF2YWlsYWJsZSBpbiB0aGUgYGthYmxlRXh0cmFgIHBhY2thZ2UgdGhhdCBtYWtlcyB0aGlzIG1ldGhvZCAgZXh0cmVtZWx5IHVzZWZ1bCBhbmQgd29ydGggbGVhcm5pbmcuIFBsdXMsIHRoZSBjb2RlIGlzIHJlbGF0aXZlbHkgc2ltcGxlIHRvIHdyaXRlLgoKSSB3YW50IHRvIHNob3cgeW91IG9uZSBtb3JlIGZlYXR1cmUgdGhhdCBpcyBub3QgYXZhaWxhYmxlIHRoZSBvdGhlciB0YWJsZSBtZXRob2RzIHdlIGNvdmVyIGluIHRoaXMgQXNzaWdubWVudC0tLSpmbG9hdGluZyouIExldCdzIGZpcnN0IHN1YnNldCB0aGUgYG10Y2Fyc2AgZGF0YSBzZXQgc28gd2UgY2FuIG1ha2UgYSBzbWFsbCB0YWJsZS4gTmV4dCB3ZSB1c2UgdGhlIGBmdWxsX3dpZHRoYCBhbmQgYHBvc2l0aW9uYCBvcHRpb25zIHRvIGNvbnRyb2wgdGhlIHNpemUgYW5kIHBvc2l0aW9uIG9mIHRoZSB0YWJsZS4gCgpIZXJlIGlzIG91ciBjb2RlIGNodW5rLgoKYGBge3Iga2FibGVfZmxvYXR9Cm10Y2Fyc19zdWIgPC0gbXRjYXJzWzE6NywxOjZdCmthYmxlKG10Y2Fyc19zdWIpICU+JQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSAic3RyaXBlZCIsCiAgICAgICAgICAgICAgICBmdWxsX3dpZHRoID0gRkFMU0UsCiAgICAgICAgICAgICAgICBwb3NpdGlvbiA9ICJmbG9hdF9yaWdodCIpCmBgYAoKPGJyLz48YnIvPgoKTGV04oCZcyBzYXkgd2UgaGF2ZSBhIGJ1bmNoIG9mIHRleHQgdGhhdCB3ZSB3YW50IHRvIHB1dCBzaWRlLWJ5LXNpZGUgd2l0aCB0aGlzIHNtYWxsIHRhYmxlLiBPdXIgc3Vic2V0dGVkIGBtdGNhcnNgIGRhdGEgc2V0IG5vdyBoYXMgYHIgbnJvdyhtdGNhcnNfc3ViKWAgcm93cyBhbmQgYHIgbmNvbChtdGNhcnNfc3ViKWAgY29sdW1ucy4gV2UgY2FuIG1ha2Ugb3VyIHRhYmxlIHNtYWxsZXIgYnkgc2V0dGluZyBgZnVsbF93aWR0aCA9IEZBTFNFYCBpbiBga2FibGVfc3R5bGluZ2AgYW5kIGZsb2F0IHRoZSB0YWJsZSBieSBzZXR0aW5nIGBwb3NpdGlvbiA9ICJmbG9hdF9yaWdodCJgCgpQbGVhc2Ugc3R1ZHkgdGhlIFtleHRlbnNpdmUgb3B0aW9ucyBhdmFpbGFibGUgaW4gYGthYmxlYCBhbmQgYGthYmxlRXh0cmFgXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMva2FibGVFeHRyYS92aWduZXR0ZXMvYXdlc29tZV90YWJsZV9pbl9odG1sLmh0bWwpIGFuZCBjcmVhdGUgdGFibGVzIHRoYXQgaW1wbGVtZW50IHNvbWUgb2YgdGhlIG9wdGlvbnMuCgo8YnIvPjxici8+Cgo+ICoqUmVjb21tZW5kYXRpb24qKiBVc2UgYGthYmxlYCArIGBrYWJsZUV4dHJhYCBmb3Igc21hbGwgdGFibGVzIHdoZXJlIGV4dGVuc2l2ZSBzdHlsaW5nIGlzIGRlc2lyZWQuCgojIyMgMi40IERUIFRhYmxlcwoKVGhlIGxhc3Qgb3B0aW9uIEkgd2FudCB0byBjb3ZlciBmb3IgYnVpbGRpbmcgdGFibGVzIGlzIGltcGxlbWVudGVkIHVzaW5nIHRoZSBgZGF0YXRhYmxlYCBmdW5jdGlvbiBmcm9tIHRoZSBbRFRdKGh0dHBzOi8vcnN0dWRpby5naXRodWIuaW8vRFQvKSBwYWNrYWdlLCBhbiBpbnRlcmZhY2UgdG8gdGhlIEphdmFTY3JpcHQgbGlicmFyeSAqW0RhdGFUYWJsZXNdKGh0dHBzOi8vZGF0YXRhYmxlcy5uZXQvKSouIFRvIGRlbW9uc3RyYXRlIHRoZSBmdW5jdGlvbmFsaXR5LCBJIHdpbGwgdXNlIGEgbGFyZ2VyIGRhdGEgc2V0IGNhbGxlZCBgVVNKdWRnZVJhdGluZ3NgIGZyb20gdGhlIGBkYXRhc2V0c2AgcGFja2FnZS4gYFVTSnVkZ2VSYXRpbmdzYCBoYXMgYHIgbnJvdyhVU0p1ZGdlUmF0aW5ncylgIHJvd3MgYW5kIGByIG5jb2woVVNKdWRnZVJhdGluZ3MpYCBjb2x1bW5zLiBUaGlzIHRhYmxlIGlzIHRvbyBiaWctLS1ob3Jpem9udGFsbHkgYW5kIHZlcnRpY2FsbHktLS10byBmaXQgb24gYSBzdGFuZGFyZCBwYWdlLgoKVGhlIHN5bnRheCBmb3IgdGhlIGBEVDo6ZGF0YXRhYmxlYCBpcyBtb3JlIGNvbXBsaWNhdGVkIHRoYW4gdGhlIG90aGVyIG1ldGhvZHMgYnV0IHRoYXQgY29tZXMgd2l0aCAgbW9yZSBleHRlbnNpdmUgZnVuY3Rpb25hbGl0eS4KCj4gV29ya2luZyB3aXRoIGBEVDo6ZGF0YXRhYmxlYCBpcyBhbiBhZHZhbmNlZCBsZXZlbCBza2lsbC4gSSBoaWdobHkgcmVjb21tZW5kIHlvdSBsZWFybiBob3cgdG8gdXNlIHRoZSBwYWNrYWdlLCBidXQgaXQgd2lsbCB0YWtlICBwcmFjdGljZS4KClBsZWFzZSBtYWtlIHN1cmUgeW91IGFyZSBjb21mb3J0YWJsZSB3aXRoIHRoZSBvdGhlciBtZXRob2RzIGZpcnN0IGJlZm9yZSB0cnlpbmcgdG8gdXNlIGBEVDo6ZGF0YXRhYmxlYC4gSSBwcm9taXNlLCBpZiB5b3UgZG8gbm90IGtub3cgd2hhdCB5b3UgYXJlIGRvaW5nLCB0aGlzIHBhY2thZ2Ugd2lsbCBjYXVzZSBhIGxvdCBvZiBmcnVzdHJhdGlvbi4gVGhhdCBzYWlkLCBJIHVzZSBpdCBhbGwgdGhlIHRpbWUgYmVjYXVzZSBpdCBpcyBhd2Vzb21lLgoKTW92aW5nIG9uLiBJZiB3ZSBydW4gYERUYCBvbiB0aGUgYFVTSnVkZ2VSYXRpbmdzYCBkYXRhIHNldCB3aXRob3V0IGFueSBvcHRpb25zIHRoZSB0YWJsZSB3aWxsIHNwaWxsIG9mZiB0aGUgc2lkZSBvZiB0aGUgcGFnZS4gQWdhaW4sIG5vdCBjb29sLiBUcnkgdG8gcnVuIHRoaXMgY29tbWFuZCBhbmQgc2VlIHdoYXQgaGFwcGVucy4KCmBgYApkYXRhdGFibGUoVVNKdWRnZVJhdGluZ3MpCmBgYAoKYERUOjpkYXRhdGFibGVgICpkb2VzIG5vdCBwYWdlIHRhYmxlcyBob3Jpem9udGFsbHkqIGxpa2UgdGhlIGBwYWdlZF90YWJsZWAgY29tbWFuZCBkb2VzIChkZXNjcmliZWQgYWJvdmUpLiBXZSBjYW4gc2V0IHRoZSB3aWR0aCBvZiB0aGUgdGFibGUgYW5kIGFkZCBhbiBvcHRpb24gdGhhdCBhbGxvd3MgaG9yaXpvbnRhbCBzY3JvbGxpbmcuIEZvciB0aGlzIHdlIHVzZSB0aGUgYG9wdGlvbnNgIGFyZ3VtZW50LiBUaGUgc3ludGF4IGlzIHRvIGFkZCBgd2lkdGggPSAiMTAwJSJgIGZvbGxvd2VkIGJ5IGBvcHRpb25zID0gbGlzdCgpYCwgd2hlcmUgd2UgcHV0IGEgY29tbWEgc2VwYXJhdGVkIGxpc3Qgb2Ygb3B0aW9ucy4gRm9yIG5vdywgd2UganVzdCBpbmNsdWRlIGBzY3JvbGxYYCBpbiBvdXIgbGlzdCBvZiBvcHRpb25zLgoKYGBge3IgZHR9CmRhdGF0YWJsZShVU0p1ZGdlUmF0aW5ncywgd2lkdGggPSAiMTAwJSIsCiAgICAgICAgICBvcHRpb25zID0gbGlzdChzY3JvbGxYID0gVFJVRSkpCmBgYAoKPGJyLz4KClBsYXkgYXJvdW5kIHdpdGggdGhlIHRhYmxlIGEgbGl0dGxlLiBBcyB5b3UgY2FuIHNlZQoKKiB0aGUgdGFibGUgbm93IGZpdHMgaW4gdGhlIHdpbmRvdywKKiBob3Jpem9udGFsIHNjcm9sbGluZyBpbiBlbmFibGVkLAoqIHRoZSBwYWdlIGlzIHZlcnRpY2FsbHkgcGFnZWQsCiogdGhlcmUgaXMgYSAqU2hvdyBlbnRyaWVzKiBkcm9wIGRvd24sIGFuZAoqIHRoZXJlIGlzIGEgKlNlYXJjaCogYm94LgoKVGhlICpTaG93IGVudHJpZXMqIGFuZCAqU2VhcmNoKiBib3ggYXJlIGFkZGVkIGJ5IGRlZmF1bHQuIFdlIGNhbiBkZWNpZGUgd2hldGhlciB0byBzaG93IHRoZXNlIG9wdGlvbnMgb3Igbm90LiBJIHdpbGwgc2F2ZSB0aGF0IGZvciBsYXRlci4gRm9yIG5vdywgSSB3YW50IHRvIGxlYXZlIHlvdSB3aXRoIGEgbW9yZSBzdHlsaXplZCBEVCBkYXRhIHRhYmxlIHRvIGdpdmUgeW91IGEgc2Vuc2Ugb2YgdGhlIHBvc3NpYmlsaXRpZXMuIERvbid0IHdvcnJ5IHNvIG11Y2ggYWJvdXQgdGhlIGNvZGUtLS1wYXkgYXR0ZW50aW9uIHRvIHRoZSBmdW5jdGlvbmFsaXR5LgoKYGBge3IgZHRfamF6en0KZGF0YXRhYmxlKFVTSnVkZ2VSYXRpbmdzLCB3aWR0aCA9ICIxMDAlIiwKICAgICAgICAgIGV4dGVuc2lvbnMgPSAnQnV0dG9ucycsIG9wdGlvbnMgPSBsaXN0KAogICAgICAgICAgICBzY3JvbGxYID0gVFJVRSwKICAgICAgICAgICAgZG9tID0gJ2xmcnRpcEInLAogICAgICAgICAgICBidXR0b25zID0gYygnY29weScsICdjc3YnLCAnZXhjZWwnLCAncGRmJywgJ3ByaW50JyksCiAgICAgICAgICAgIHBhZ2VMZW5ndGggPSA1LAogICAgICAgICAgICBsZW5ndGhNZW51ID0gYyg1LCAxMCwgMjAsIDQ1KQogICAgICAgICAgICApCiAgICAgICAgICApCmBgYAo8YnIvPjxici8+CgpJIGFkZGVkIGJ1dHRvbnMgdG8gZG93bmxvYWQgdGhlIHRhYmxlIHRvIGRpZmZlcmVudCBmb3JtYXRzLCBjaGFuZ2VkIHRoZSBwYWdlIGxlbmd0aCB0byA1LCBhbmQgY2hhbmdlZCB0aGUgdmFsdWVzIGluIHRoZSAqU2hvdyBlbnRyaWVzKiBkcm9wIGRvd24uIFBsYXkgYXJvdW5kIHdpdGggdGhlIHRhYmxlLiBUaGVyZSBpcyBhIGxvdCBtb3JlIHRvIGRvIHdpdGggdGhpcyBwYWNrYWdlIGFuZCB3ZSB3aWxsIGNvbWUgYmFjayB0byBpdCBvZnRlbi4KCj4gKipSZWNvbW1lbmRhdGlvbioqIFVzZSBgRFQ6OmRhdGF0YWJsZWAgZm9yIGxhcmdlIHRhYmxlcyB3aGVyZSBleHRlbnNpdmUgc3R5bGluZyBpcyBkZXNpcmVkLgoKVGhhdOKAmXMgYWxsIGZvciB0aGlzIGFzc2lnbm1lbnQuIAoKIyMgQXNzaWdubWVudCAzOiBDb2RlCgpJZiB5b3UgYXJlIGludGVyZXN0ZWQgaW4gbWFraW5nIHlvdXIgc2NpZW5jZSBtb3JlIHRyYW5zcGFyZW50IGFuZCByZXByb2R1Y2libGUsIHlvdSBuZWVkIHRvIHByb3ZpZGUgYXQgbGVhc3QgdHdvIHRoaW5ncy0tLXRoZSByYXcgZGF0YSB5b3UgZ2VuZXJhdGVkIGFuZCB0aGUgY29kZSB5b3UgdXNlZCB0byBhbmFseXplIGl0LiBIb3BlZnVsbHkgaXQgaXMgb2J2aW91cyBieSBub3cgdGhhdCB5b3UgbmVlZCB0byBwcm92aWRlIGFjY2VzcyB0byAqKipib3RoKioqIGNvbXBvbmVudHM7IG5laXRoZXIgaXMgcGFydGljdWxhcmx5IHVzZWZ1bCB3aXRob3V0IHRoZSBvdGhlci4gV2Ugd2lsbCBjb3ZlciBkYXRhIGF2YWlsYWJpbGl0eSBpbiBhIGZ1dHVyZSBsZXNzb24uIEZvciB0aGlzIGFzc2lnbm1lbnQsIHlvdSB3aWxsIHByYWN0aWNlIHNldmVyYWwgZGlmZmVyZW50IG1ldGhvZHMgZm9yIG1ha2luZyB5b3VyIGNvZGUgYWNjZXNzaWJsZS4gVGhlIG1ldGhvZCBvciBtZXRob2RzIHlvdSBjaG9vc2UgZm9yIHlvdXIgb3duIHdvcmsgd2lsbCBkZXBlbmQgb24gdGhlIHR5cGUgb2YgYW5hbHlzZXMgKmFuZCogdGhlIHR5cGUgb2YgY29kZS4gCgo+IFlvdXIgYXNzaWdubWVudCBpcyB0byBpbXBsZW1lbnQgdGhlc2UgbWV0aG9kcyBpbiB5b3VyIGRvY3VtZW50IGFuZCBwbGF5IGFyb3VuZCB3aXRoIHRoZSBkaWZmZXJlbnQgb3B0aW9ucy4gCgojIyMgUHVybAoKS25pdHIgY29tZXMgd2l0aCBhIGJ1aWx0LWluIGZ1bmN0aW9uIGNhbGxlZCBgcHVybGAsIHdoaWNoIGFsbG93cyB5b3UgdG8gZXh0cmFjdCBhbGwgdGhlIFIgY29kZSBmcm9tIGFuIFIgTWFya2Rvd24gZG9jdW1lbnQgYW5kIGNvbnZlcnQgaXQgdG8gYW4gUiBzY3JpcHQuIEluIG9yZGVyIHRvIHJ1biBgcHVybGAsIHlvdSBtdXN0IGVpdGhlciBsb2FkIHRoZSBrbml0ciBsaWJyYXJ5IGZpcnN0IChpLmUuLCBgbGlicmFyeShrbml0cilgKSBhbmQgdGhlbiBydW4gYHB1cmxgIG9yIGNhbGwgdGhlIGZ1bmN0aW9uIGRpcmVjdGx5IGJ5IHJ1bm5pbmcgYGtuaXRyOjpwdXJsKClgLiBXZSB3aWxsIHN0YXJ0IGJ5IGRpc2N1c3Npbmcgc29tZSBzaW1wbGUgKm9wdGlvbnMqIGZvciBydW5uaW5nIGBwdXJsYCBhbmQgdGhlbiB0YWxrIGFib3V0ICpob3cqIHlvdSBydW4gdGhlIGNvbW1hbmQuIFRoZSBiYXNpYyBzdHJ1Y3R1cmUgb2YgdGhlIGNvbW1hbmQgaXM6Cgo+IGBrbml0cjo6cHVybChpbnB1dD0iZmlsZW5hbWUuUm1kIiwgZG9jdW1lbnRhdGlvbiA9IEwpYAoKQnkgZGVmYXVsdCwgYHB1cmxgIHVzZXMgdGhlIGJhc2UgbmFtZSBvZiB0aGUgaW5wdXQgZmlsZSBhcyB0aGUgYmFzZSBuYW1lIG9mIHRoZSBvdXRwdXQgZmlsZS4gSWYgeW91IHdhbnQgdG8gY29udHJvbCB0aGlzIGJlaGF2aW9yLCBhZGQgdGhlIG9wdGlvbiBgb3V0cHV0PSJmaWxlbmFtZS5SImAgd2hlcmUgYGZpbGVuYW1lYCBpcyB3aGF0ZXZlciB5b3UgY2hvb3NlLiAKClRoZSBvcHRpb24gYGRvY3VtZW50YXRpb25gIGlzIGFuIGludGVnZXIgdGhhdCBzcGVjaWZpZXMgdGhlIGxldmVsIChgTGApIG9mIGRvY3VtZW50YXRpb24gdG8gYWRkIHRvIHRoZSBzY3JpcHQuIFlvdSBoYXZlIHRocmVlIGNob2ljZXMKCiogKiowKiogbWVhbnMgb3V0cHV0IHB1cmUgY29kZSB0byB0aGUgc2NyaXB0LCBkaXNjYXJkIGFsbCBNYXJrZG93biB0ZXh0IGFuZCBjb2RlIGNodW5rIGRldGFpbHMuIAoqICoqMSoqICh0aGUgZGVmYXVsdCkgbWVhbnMgZGlzY2FyZCBhbGwgTWFya2Rvd24gdGV4dCBidXQgYWRkIHRoZSBjaHVuayBoZWFkZXJzIHRvIHRoZSBzY3JpcHQgYXMgY29tbWVudGVkIGxpbmVzLiAKKiAqKjIqKiBtZWFucyB0byBhZGQgYWxsIE1hcmtkb3duIHRleHQgYW5kIGNvZGUgY2h1bmtzIHRvIHRoZSBzY3JpcHQgYXMgY29tbWVudGVkIGxpbmVzLgoKQXMgZmFyIGFzIEkga25vdywgeW91ICoqY2Fubm90KiogcnVuIGBwdXJsYCBmcm9tIGluc2lkZSBhbiBhY3R1YWwgY29kZSBjaHVuay4gSSBoYXZlIG5vIGlkZWEgd2h5IG5vciB3YXMgSSBhYmxlIHRvIGZpbmQgYW4gYW5zd2VyLiBJZiBoYXZlIGFuIGFuc3dlciBvciBrbm93IGEgc29sdXRpb24sIHBsZWFzZSBsZXQgdXMga25vdy4gVGhlcmUgKmVhc2llc3QqIHdheSB0byBnZW5lcmF0ZSBhbiBSIHNjcmlwdCBmcm9tIGFuIFIgTWFya2Rvd24gZG9jdW1lbnQgd2l0aCBgcHVybGAgdG8gIGlzIHRvIHJ1biB0aGUgY29tbWFuZCBpbiB0aGUgQ29uc29sZSBsaWtlIHNvOgoKYGtuaXRyOjpwdXJsKGlucHV0PSJmaWxlbmFtZS5SbWQiLCBkb2N1bWVudGF0aW9uID0gMSlgCgo+IFJ1biB0aGUgYHB1cmxgIGNvbW1hbmQgdXNpbmcgdGhlIHRocmVlIG9wdGlvbnMgZGVzY3JpYmVkIGFib3ZlIGZvciBgZG9jdW1lbnRhdGlvbmAgb3B0aW9uIGFuZCBsb29rIGF0IHRoZSBvdXRwdXQgZmlsZXMuIAoKSW5saW5lIFIgZXhwcmVzc2lvbnMgYXJlIGlnbm9yZWQgYnkgZGVmYXVsdC4gRm9yIGV4YW1wbGUsIGlmIHlvdSBoYWQgYW4gaW5saW5lIFIgZXhwcmVzc2lvbiBsaWtlIHRoaXMgYGAgYHIKc3FydCgyKWAgYGAgCnRoZSBleHByZXNzaW9uIHdvdWxkIG5vdCBiZSBpbmNsdWRlZCBpbiB0aGUgUiBzY3JpcHQgZ2VuZXJhdGVkIGJ5IGBwdXJsYC4gSWYgeW91IHdhbnQgdG8gaW5jbHVkZSBpbmxpbmUgZXhwcmVzc2lvbnMgaW4gdGhlIFIgc2NyaXB0LCB5b3UgbmVlZCB0byBzZXQgdGhlIGdsb2JhbCBSIG9wdGlvbiBga25pdHIucHVybC5pbmxpbmUgPSBUUlVFYCBiZWZvcmUgY2FsbGluZyBga25pdHI6OnB1cmwoKWAuIAoKUmVtZW1iZXIgd2F5IGJhY2sgd2hlbiB5b3UgZ2VuZXJhdGVkIHlvdXIgaW5pdGlhbCBSIE1hcmtkb3duIGRvY3VtZW50IGEgZGVmYXVsdCBjb2RlIGNodW5rIHdhcyBhZGRlZCBqdXN0IGJlbG93IHRoZSBZQU1MIGhlYWRlcj8KCgpgYGBgCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfWByICcnYAprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpCmBgYApgYGBgCgpJZiB5b3UgYWRkIGBrbml0ci5wdXJsLmlubGluZSA9IFRSVUVgIHRvIHRoYXQgY29kZSBjaHVuaywgYWxsIGlubGluZSBleHByZXNzaW9ucyB3aWxsIGJlIGFkZGVkIHRvIHRoZSBSIHNjcmlwdC4gCgpgYGBgCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfWByICcnYAprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsIGtuaXRyLnB1cmwuaW5saW5lID0gVFJVRSkKYGBgCmBgYGAKClRoZSBsYXN0IHRoaW5nIEkgd2FudCB0byBtZW50aW9uIGlzIHRoYXQgeW91IGNhbiAqcHJldmVudCogY2VydGFpbiBjb2RlIGNodW5rcyBmcm9tIGFwcGVhcmluZyBpbiB0aGUgUiBTY3JpcHQgYnkgYWRkaW5nIHRoZSBvcHRpb24gYHB1cmwgPSBGQUxTRWAgdG8gdGhlIGNodW5rLiBGb3IgZXhhbXBsZSwgaWYgeW91IGFkZCB0aGlzIG9wdGlvbiB0byB0aGUgYHNldHVwYCBjaHVuayB3ZSBqdXN0IGRpc2N1c3NlZCB0aGF0IGNodW5rIHdpbGwgbm90IGFwcGVhciBpbiB0aGUgZmluYWwgZG9jdW1lbnQuICAKCmBgYGAKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0UsIHB1cmwgPSBGQUxTRX1gciAnJ2AKa25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCBrbml0ci5wdXJsLmlubGluZSA9IFRSVUUpCmBgYApgYGBgCgpUZXN0IHRoZSBiZWhhdmlvciBvZiB0aGUgZGlmZmVyZW50IG9wdGlvbnMgZm9yIGBwdXJsYCBvbiB5b3VyIGRvY3VtZW50LiBZb3UgY2FuIGFsc28gdXNlIHRoaXMgZnVudGlvbiBvbiAqYW55KiBSIE1hcmtkb3duIGRvY3VtZW50IHRvIHF1aWNrbHkgcmV0cmlldmUgdGhlIGNvZGUuIEZvciBleGFtcGxlLCBpZiB5b3UgZG93bmxvYWQgdGhlIFJtZCBmaWxlIGZvciB0aGlzIHBhZ2UgZnJvbSBHaXRIdWIgeW91IGNhbiBydW4gYHB1cmxgIHRvIHF1aWNrbHkgZXh0cmFjdCB0aGUgUiBjb2RlLiAgCgo+ICoqUmVjb21tZW5kYXRpb24qKiBVc2UgYHB1cmxgIHRvIGdlbmVyYXRlIGEgc2ltcGxlIFIgc2NyaXB0IHZlcnNpb24gb2YgeW91ciBSIE1hcmtkb3duIGRvY3VtZW50ICphZnRlciogdGhlIGRvY3VtZW50IGlzIGZpbmlzaGVkIGFuZCBzYXZlZC4gWW91IGNhbiB0aGVuIGxpbmsgdG8gdGhlIGZpbGUgc29tZXdoZXJlIGluIHlvdXIgZG9jdW1lbnQuIAoKIyMjIERvd25sb2FkIFJtZAoKSSBob3BlIGJ5IG5vdyB5b3UgaGF2ZSBzZWVuIHRoYXQgYW55IGRvY3VtZW50IEkgcHJlc2VudCBpbiB0aGlzIGNvdXJzZSBoYXMgYSBsaW5rIHRvIGEgR2l0SHViIHJlcG8gd2hlcmUgeW91IGNhbiBkb3dubG9hZCBvciBjb3B5IHRoZSBgLlJtZGAgZmlsZS4gVGhhdCdzIGdyZWF0IGFuZCBhbGwsIGJ1dCB3b3VsZG4ndCBpdCBiZSBuaWNlIGlmIHlvdSBjb3VsZCBkbyBpdCByaWdodCBmcm9tIHRoZSBIVE1MIHBhZ2U/IFdlbGwsIHlvdSBjYW4gYnkgYWRkaW5nIG9uZSBzaW1wbGUgbGluZSBvZiBjb2RlIGFzIGEgcHJvcGVydHkgb2YgYGh0bWxfZG9jdW1lbnRgIGluIHlvdXIgWUFNTCBoZWFkZXIgLS0tYGNvZGVfZG93bmxvYWQ6IHRydWVgLiAKCmBgYApvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIHRoZW1lOiBqb3VybmFsCiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgdG9jX2RlcHRoOiAzCiAgICBoaWdobGlnaHQ6IHRhbmdvCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCmBgYAoKWW91IGNvdWxkIG9mIGNvdXJzZSBzZXQgdGhlIHByb3BlcnR5IHRvIGBmYWxzZWAgZXhjZXB0IHRoaXMgaXMgdGhlIGRlZmF1bHQgdmFsdWUgYW5kIG5vdGhpbmcgd2lsbCBjaGFuZ2UuIExvb2sgYmFjayBhdCB0aGUgdG9wIG9mIHRoaXMgcGFnZSBhbmQgeW91IHNob3VsZCBub3cgc2VlIGEgYENvZGVgIGJ1dHRvbiBpbiB0aGUgdXBwZXIgcmlnaHQgY29ybmVyLiBDbGljayBvbiB0aGUgZHJvcCBkb3duIGFuZCBzZWxlY3QgYERvd25sb2FkIFJtZGAgYW5kIHRoaXMgZW50aXJlIHBhZ2Ugc2hvdWxkIGJlIHNhdmVkIHRvIHlvdXIgRG93bmxvYWRzIGRpcmVjdG9yeS4gCgo+IEdvIGFoZWFkIGFuZCBhZGQgdGhpcyBvcHRpb24gdG8geW91ciBZQU1MIGhlYWRlci4KCiMjIyBDb2RlIEZvbGRpbmcKCkkgaGF2ZSBtZW50aW9uZWQgYSB0aW1lIG9yIHR3byB0aGF0IHRoZSBiZW5lZml0cyBvZiB1c2luZyBSIE1hcmtkb3duIGlzIHRoZSBhYmlsaXR5IHRvICoqKmV4ZWN1dGUqKiogYW5kICoqKmRpc3BsYXkqKiogY29kZSBpbiB5b3VyIGZpbmFsIGRvY3VtZW50LiBJZiB5b3UgZ28gYmFjayB0byB0aGUgZGVmYXVsdCBgc2V0dXBgIGNodW5rIGF0IHRoZSB0b3Agb2YgeW91ciBgLlJtZGAgeW91IHNob3VsZCBzZWUgdGhpczoKCmBgYAprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpCmBgYAoKSSBkaXNjdXNzZWQgdGhpcyBjaHVuayBwcmV2aW91c2x5IGluICM1IG9mIHRoZSBbQ2h1bmsgc3RydWN0dXJlICYgb3B0aW9uc10oaHR0cHM6Ly9zdHJpLWNvbi5naXRodWIuaW8vZGF0YS1jdXJhdGlvbi8yMDIwLzA0LzA5L2xlc3Nvbi0yLyNjaHVuay1zdHJ1Y3R1cmUtb3B0aW9ucy0xKSBzZWN0aW9uIGluIExlc3NvbiAyLiBCcmllZmx5LCB0aGlzIGlzIGEgKmdsb2JhbCBjb21tYW5kKiB0aGF0IGVuc3VyZXMgYWxsIFIgY29kZSBjaHVua3MgYXJlIHZpc2libGUgaW4gdGhlIGZpbmFsIGRvY3VtZW50LCB1bmxlc3MgeW91IGVzY2FwZSB0aGlzIGJlaGF2aW9yIGJ5IHVzaW5nIGBlY2hvID0gRkFMU0VgIGluIGEgcGFydGljdWxhciBjaHVuay4gT2YgY291cnNlLCB5b3UgY291bGQgYWxzbyBzZXQgdGhlIGdsb2JhbCBvcHRpb24gdG8gYEZBTFNFYCBhcyBpcyBga25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBGQUxTRSlgIGFuZCB0aGVuIG5vbmUgb2YgdGhlIFIgY29kZSB3b3VsZCBiZSB2aXNpYmxlIGF0IGFsbC4gVGhpcyBpcyBhIHBlcmZlY3RseSBmaW5lIG9wdGlvbiBpbiBzb21lIHNpdHVhdGlvbnMgYnV0IG5vdCBpbiBvdGhlcnMuIAoKTGV0J3MgZmFjZSBpdC0tLWNvZGUgdGFrZXMgdXAgYSBsb3Qgb2Ygc3BhY2UgaW4gYSBkb2N1bWVudCBhbmQgbGFyZ2UgY29kZSBjaHVua3MgYXJlIG5vdCBwYXJ0aWN1bGFybHkgcGxlYXNpbmcgdG8gbG9vayBhdC4gWW91IG1heSBlbmNvdW50ZXIgc2l0dWF0aW9ucyB3aGVyZSB5b3UgYm90aCB3YW50IHRoZSBjb2RlIGF2YWlsYWJsZSBvbiBhIHBhZ2UgKmJ1dCogeW91IGFsc28gd2FudCB0byBoaWRlIHRoZSBjb2RlLiBGb3IgdGhpcyB3ZSB1c2UgYSB0ZWNobmlxdWUgY2FsbGVkICoqKmNvZGUgZm9sZGluZyoqKi4gTmVhciB0aGUgYm90dG9tIG9mIFtMZXNzb24gMF0oaHR0cHM6Ly9zdHJpLWNvbi5naXRodWIuaW8vZGF0YS1jdXJhdGlvbi8yMDIwLzAzLzI4L2xlc3Nvbi0wLyksIEkgdXNlZCBzb21lIHNpbXBsZSBIVE1MIHRvIG1ha2UgYSBzZWN0aW9uIHRoYXQgZm9sZHMgdGhlIFIgY29kZSBmb3IgdGhlIENsaWZmb3JkIEF0dHJhY3Rvci4gVGhlcmUgaXMgYSBsaXR0bGUgYFNob3cvaGlkZWAgYnV0dG9uIHRoYXQgYWxsb3dzIHlvdSB0byBsb29rIGF0IHRoZSBjb2RlIGlmIHlvdSB3YW50IHRvOyBvdGhlcndpc2UgaXQgaXMgaGlkZGVuIGJ5IGRlZmF1bHQuIEJ1dCB0aGlzIGFwcHJvYWNoIGlzIGEgbGl0dGxlIGNsdW5reSBiZWNhdXNlIHlvdSBtdXN0ICoqYSoqKSBrbm93IHNvbWUgSFRNTCBhbmQgKipiKiopIGluY2x1ZGUgdGhpcyBmb3IgZXZlcnkgY2h1bmsuIAoKUiBNYXJrZG93biBoYXMgYSBzaW1pbGFyIGZ1bmN0aW9uYWxpdHkgZm9yIHNob3dpbmcgYW5kIGhpZGluZyBjb2RlIGJ1dCBpdCBvbmx5IHRha2VzIGEgc2luZ2xlIGxpbmUgb2YgY29kZSBhZGRlZCB0byB0aGUgWUFNTCBoZWFkZXIuIEFnYWluLCByZXR1cm4gdG8geW91ciBZQU1MIGhlYWRlciBhbmQgYWRkIHRoZSBhcmd1bWVudCAgYGNvZGVfZm9sZGluZzpgIGFzIGEgbmVzdGVkIHByb3BlcnR5IG9mIGBodG1sX2RvY3VtZW50OmAuIFlvdXIgdHdvIG9wdGlvbnMgZm9yIGBjb2RlX2ZvbGRpbmc6YCBhcmUgYHNob3dgIGFuZCBgaGlkZWAuIAoKYGBgCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgdGhlbWU6IGpvdXJuYWwKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICB0b2NfZGVwdGg6IDMKICAgIGhpZ2hsaWdodDogdGFuZ28KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIGNvZGVfZm9sZGluZzogaGlkZQpgYGAKCk9uY2UgeW91IGFkZCB0aGlzIHRvIHRoZSBZQU1MIGhlYWRlciwgdGhlIGRyb3AgZG93biBgQ29kZWAgYnV0dG9uIGluIHRoZSB1cHBlciByaWdodCBjb3JuZXIgb2YgdGhlIHBhZ2Ugc2hvdWxkIG5vdyBpbmNsdWRlIGBTaG93IEFsbCBDb2RlYCBhbmQgYEhpZGUgQWxsIENvZGVgLiBUaGlzIGFsbG93cyB0aGUgdXNlciB0byBzcGVjaWZ5IGhvdyB0aGV5IHdhbnQgdG8gdmlldyB0aGUgY29kZSBpbiB0aGUgZG9jdW1lbnQuIEVpdGhlciBwcm9wZXJ0eSB5b3Ugc2V0IGZvciBgY29kZV9mb2xkaW5nYCB3aWxsIGJlIHRoZSBkZWZhdWx0IHN0YXRlIGZvciB0aGUgZW50aXJlIGRvY3VtZW50LiAKCllvdSBzaG91bGQgYWxzbyBub3RpY2UgdGhhdCBhIG5ldyBgQ29kZWAgYnV0dG9uIGFwcGVhcnMgbmV4dCB0byBldmVyeSBjb2RlIGNodW5rIGluIHlvdXIgZG9jdW1lbnQuIEFnYWluLCBpZiB5b3Ugd2FudCB0byBleGNsdWRlIHRoZSBjb2RlIGZyb20gaW5kaXZpZHVhbCBjaHVua3MsIGp1c3Qgc2V0IGBlY2hvID0gRkFMU0VgIGZvciB0aGF0IGNodW5rIGFuZCB0aGUgY29kZSB3aWxsIG5vdCBiZSBpbmNsdWRlZCBhdCBhbGwuIAoKPiBBZGQgYGNvZGVfZm9sZGluZzpgIGFyZ3VtZW50IHRvIHlvdXIgWUFNTCBoZWFkZXIgYW5kIHNldCBhIHByb3BlcnR5IHZhbHVlLiAKCjxici8+CgpBcyBmYXIgYXMgSSBrbm93IHRoZXJlIGlzIG5vIHdheSBvZiBmb2xkaW5nIHRoZSAqcmVzdWx0cyogb2YgYSBjb2RlIGNodW5rIG9yIGZvbGRpbmcgaW5kaXZ1ZHVhbCBjaHVua3MgdW5sZXNzIHlvdSB1c2UgSFRNTC4gCgpUaGF0J3MgYWxsIGZvciB0aGlzIGFzc2lnbm1lbnQuIAoKIyMgU2Vzc2lvbiBJbmZvCgpgYGB7ciBzZXNzaW9ufQpzZXNzaW9uSW5mbygpCmBgYAo=